嵌入式单片机基础篇(三十四)之I2C通信以及stm32单片机程序详解

I2C通信以及stm32单片机程序详解

1、初始化IO口:

#define IIC_SCL    PBout(6) //SCL
#define IIC_SDA    PBout(7) //SDA	 
#define READ_SDA   PBin(7)  //输入SDA 

(1)在固件库中操作IDR寄存器读取IO端口数据是通过GPIO_ReadInputDataBit函数实现的:
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
比如 要读GPIOA.5的电平状态,那么方法是: GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5);
返回值是1(Bit_SET)或者0(Bit_RESET);
在STM32固件库中,通过BSRR和BRR寄存器设置GPIO端口输出是通过函数 GPIO_SetBits()和函数GPIO_ResetBits()来完成的。
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) ;
在多数情况下,都是采用这两个函数来设置GPIO端口的输入和输出状态。
比如要设置GPIOB.5输出1,方法为:
GPIO_SetBits(GPIOB, GPIO_Pin_5);
如果要设置GPIOB.5输出0,方法为:
GPIO_ResetBits (GPIOB, GPIO_Pin_5);
(2)位带操作:
宏定义:
#define LED0 PBout(5)
#define LED1 PEout(5)

位带操作来实现操作某个IO口的1个位,通过位带操作PB5输出高低电平的方法如下:
LED0=1; //通过位带操作控制引脚PB5输出高电平
LED0=0; //通过位带操作控制引脚PB5输出低电平
比如,要PORTA的第七个IO口输出1,PAout(6)=1;
要判断PORTA的第15个位是否等于1,则可以使用if(PAin(14)==1)…;

void IIC_Init(void)
{
   					     
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	//使能GPIOB时钟   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7); 	//PB6,PB7 输出高
}

2、初始化时钟线SCL与数据线SDA,此时可以看到这两个引脚都是输出引脚,根据I2C通信协议可知:SDA信号线上不仅仅只输出信号,有时也有输入信号,也就是说SDA信号线的引脚有时需要配置成输出,有时需要配置成输入,程序如下:

void IIC_setSDAMode_Out(void)
{
   
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	//使能GPIOB时钟   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //PB7推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

void IIC_setSDAMode_In(void)
{
   
  GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	//使能GPIOB时钟  
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPU ;   //推挽输出
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

3、信号线的引脚初始化状态配置好后,开始写I2C通信协议,程序如下:
(1)起始信号:

void IIC_Start(void)
{
   
	IIC_setSDAMode_Out();     //sda线输出
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	delay_us(4);
 	IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
}	

注意:起始信号产生后,SCL信号线为低电平状态
(2)写单字节函数:

void IIC_Send_Byte(u8 txd)
{
                           
    u8 t;   
	IIC_setSDAMode_Out(); 	    
    for(t=0;t<8;t++)
    {
                 
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1; 	  
		delay_us(2);   //对TEA5767这三个延时都是必须的
		IIC_SCL=1;
		delay_us(2); 
		IIC_SCL=0;	
		delay_us(2);
    }	 
} 	

注意:写单字节函数完成后,SCL信号线为低电平状态
(3)读单字节函数:

u8 IIC_Read_Byte()
{
   
	unsigned char i,receive=0;
    IIC_setSDAMode_In();//SDA设置为输入
    for(i=0;i<8;i++ )
	{
   
       IIC_SCL=1; 
	   receive<<=1;
	   receive|=(unsigned char)READ_SDA; 
	   IIC_SCL=0;
       delay_us(2);
    }					 
       return receive;
}

注意:读单字节函数完成后,SCL信号线为低电平状态
(4)应答信号:

u8 IIC_Wait_Ack(void)
{
   
	u8 a;
	IIC_setSDAMode_In();      //SDA设置为输入  
	IIC_SDA=1;delay_us(1);	   
	IIC_SCL=1;delay_us

你可能感兴趣的:(AT24C02,嵌入式,单片机,嵌入式,字符串,单片机,stm32,IIC)