网上发现的一个stm32的I2C比较通俗易懂的入门例程。

买了个核心板,算是有自己的STM32板子了,所以顺便也整一整I2C(因为上面的是24C02,嘻嘻,比较亲切),刚开始的时候,按照参考书上面的例程写了一个读写程序,但是直接把程序下载到板子里串口无数据输出(我是用的串口把读出的数据发送出来),然后我就在FLASH里调试,一步步的走下去,发现程序停在了 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED)){;},然后就是找各种可能的原因,最后实在不行了就百度了一下,发现了一条重要信息: 有些IIC设备读写的时候需要加延时!感觉可能是这个原因,毕竟24C02是I2C的入门级芯片,于是就在程序加了延时函数,下载到板子里,通了!感谢网络上的各位前辈!
下面贴出源代码:
#include <stm32f10x.h>
#include "I2C.h"
#include <stm32f10x_gpio.h>
#include <stm32f10x_i2c.h>

void I2C_GPIO_Config()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}

void I2C1_Init()
{
I2C_InitTypeDef I2C_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0xA0;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 400000;
I2C_Cmd(I2C1, ENABLE);
I2C_Init(I2C1, &I2C_InitStructure);
}

void I2C_Write(u8 addr, u8 data)
{
I2C_AcknowledgeConfig(I2C1,ENABLE); //使能应答
I2C_GenerateSTART(I2C1,ENABLE); //发送一个开始位
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)){;}//等待EV5
I2C_Send7bitAddress(I2C1,0xA0,I2C_Direction_Transmitter); //发送从地址
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){;} //等待EV6
I2C_SendData(I2C1,addr); //发送要写入数据的地址
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)){;} //等待EV8
I2C_SendData(I2C1,data); //发送要写入的数据
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)){;} //等待EV8
I2C_GenerateSTOP(I2C1,ENABLE); //发送停止位
}

u8 I2C_Read(u8 nAddr)
{
I2C_AcknowledgeConfig(I2C1,ENABLE); //使能应答
I2C_GenerateSTART(I2C1,ENABLE); //发送一个开始位
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)){;} //等待EV5
I2C_Send7bitAddress(I2C1,0xA0,I2C_Direction_Transmitter); //发送一个伪写指令
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){;}//等待EV6
I2C_SendData(I2C1,nAddr);//发送读地址
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)){;} //等待EV8

I2C_GenerateSTART(I2C1,ENABLE); //发送一个开始位
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT)){;} //等待EV5
I2C_Send7bitAddress(I2C1,0xA0,I2C_Direction_Receiver); //发送一个读指令
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)){;} //等待EV6
I2C_AcknowledgeConfig(I2C1,DISABLE); //应答使能关闭
I2C_GenerateSTOP(I2C1,ENABLE); //发送一个停止位
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED)){;} //等待EV7
return I2C_ReceiveData(I2C1); //返回读到的数据
}

#include<stm32f10x_lib.h>
#include"usart.h"

void usart_gpio_config()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA,&GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA,&GPIO_InitStructure);

}

void usart_init()
{
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1,&USART_InitStructure);
USART_Cmd(USART1,ENABLE);
}

void usart_putchar(u8 ch)
{
USART_SendData(USART1,ch);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
}

#include <stm32f10x.h>
#include "delay.h"
static u8 fac_us=0;//us延时倍乘数
static u16 fac_ms=0;//ms延时倍乘数
//初始化延迟函数
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void delay_init(u8 SYSCLK)
{
SysTick->CTRL&=0xfffffffb;//bit2清空,选择外部时钟 HCLK/8
fac_us=SYSCLK/8;
fac_ms=(u16)fac_us*1000;
}
//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对72M条件下,nms<=1864
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00; //清空计数器
SysTick->CTRL=0x01 ; //开始倒数
do
{
temp=SysTick->CTRL;
}
while(temp&0x01&&!(temp&(1<<16)));//等待时间到达
SysTick->CTRL=0x00; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
//延时nus
//nus为要延时的us数.
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD=nus*fac_us; //时间加载
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL=0x01 ; //开始倒数
do
{
temp=SysTick->CTRL;
}
while(temp&0x01&&!(temp&(1<<16)));//等待时间到达
SysTick->CTRL=0x00; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}

#include <stm32f10x.h>
#include "I2C.h"
#include "Usart.h"
#include "delay.h"

int main()
{
SystemInit();
delay_init(72);
I2C_GPIO_Config();
I2C1_Init();
usart_gpio_config();
usart_init();
I2C_Write(0x10,0x30);
delay_ms(10);

while(1)
{
usart_putchar(I2C_Read(0x10));
delay_ms(1000);
}
}
因为只是想试验一下,所以就只是写入一个数据,然后通过串口读出写入的数据,仅此而已。













猜你喜欢

转载自blog.csdn.net/ludaoyi88/article/details/50858994