I2C通信以及stm32单片机程序详解
1、初始化IO口:
#define IIC_SCL PBout(6)
#define IIC_SDA PBout(7)
#define READ_SDA PBin(7)
(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 );
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);
}
2、初始化时钟线SCL与数据线SDA,此时可以看到这两个引脚都是输出引脚,根据I2C通信协议可知:SDA信号线上不仅仅只输出信号,有时也有输入信号,也就是说SDA信号线的引脚有时需要配置成输出,有时需要配置成输入,程序如下:
void IIC_setSDAMode_Out(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
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 );
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();
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;
delay_us(4);
IIC_SCL=0;
}
注意:起始信号产生后,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);
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();
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();
IIC_SDA=1;delay_us(1);
IIC_SCL=1;delay_us(1);
a=READ_SDA;
IIC_SCL=0;
return a;
}
注意:应答信号产生后,SCL信号线为低电平状态 (5)结束信号:
void IIC_Stop(void)
{
IIC_setSDAMode_Out();
IIC_SDA=0;
delay_us(4);
IIC_SCL=1;
IIC_SDA=1;
delay_us(4);
}
4、AT24C02相关程序: (1)读单字节程序:
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{
u8 temp=0;
IIC_Start();
IIC_Send_Byte(0XA0+((ReadAddr/256)<<1));
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr%256);
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(0XA1);
IIC_Wait_Ack();
temp=IIC_Read_Byte();
IIC_Stop();
return temp;
}
(2)写单字节程序:
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{
IIC_Start();
IIC_Send_Byte(0XA0+((WriteAddr/256)<<1));
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr%256);
IIC_Wait_Ack();
IIC_Send_Byte(DataToWrite);
IIC_Wait_Ack();
IIC_Stop();
delay_ms(10);
}
(3)AT24C02检测函数:
u8 AT24CXX_Check(void)
{
u8 temp;
temp=AT24CXX_ReadOneByte(255);
if(temp==0X55)return 0;
else
{
AT24CXX_WriteOneByte(255,0X55);
temp=AT24CXX_ReadOneByte(255);
if(temp==0X55)return 0;
}
return 1;
}
(4)读字符串函数:
void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
{
while(NumToRead)
{
*pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);
NumToRead--;
}
}
(5)写字符串函数:
void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
{
while(NumToWrite--)
{
AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
WriteAddr++;
pBuffer++;
}
}
5、main函数:
const u8 TEXT_Buffer[]={"helloworld"};
#define SIZE sizeof(TEXT_Buffer)
int main(void)
{
u8 key;
u16 i=0;
u8 datatemp[SIZE];
delay_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(115200);
LED_Init();
LCD_Init();
KEY_Init();
AT24CXX_Init();
POINT_COLOR=RED;
while(AT24CXX_Check());
while(1)
{
key=KEY_Scan(0);
if(key==KEY1_PRES)
{
AT24CXX_Write(0,(u8*)TEXT_Buffer,SIZE);
}
if(key==KEY0_PRES)
{
AT24CXX_Read(0,datatemp,SIZE);
LCD_ShowString(30,190,200,16,16,datatemp);
}
i++;
delay_ms(10);
if(i==20)
{
LED0=!LED0;
i=0;
}
}
}
6、完整程序如下: (1)myiic.h
#ifndef __MYIIC_H
#define __MYIIC_H
#include "sys.h"
#define IIC_SCL PBout(6)
#define IIC_SDA PBout(7)
#define READ_SDA PBin(7)
void IIC_Init(void);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Send_Byte(u8 txd);
u8 IIC_Read_Byte(void);
u8 IIC_Wait_Ack(void);
void IIC_setSDAMode_Out(void);
void IIC_setSDAMode_In(void);
void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);
#endif
(2)myiic.c
#include "myiic.h"
#include "delay.h"
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
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);
}
void IIC_setSDAMode_Out(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
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 );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPU ;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void IIC_Start(void)
{
IIC_setSDAMode_Out();
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;
delay_us(4);
IIC_SCL=0;
}
void IIC_Stop(void)
{
IIC_setSDAMode_Out();
IIC_SDA=0;
delay_us(4);
IIC_SCL=1;
IIC_SDA=1;
delay_us(4);
}
u8 IIC_Wait_Ack(void)
{
u8 a;
IIC_setSDAMode_In();
IIC_SDA=1;delay_us(1);
IIC_SCL=1;delay_us(1);
a=READ_SDA;
IIC_SCL=0;
return a;
}
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);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
}
u8 IIC_Read_Byte()
{
unsigned char i,receive=0;
IIC_setSDAMode_In();
for(i=0;i<8;i++ )
{
IIC_SCL=1;
receive<<=1;
receive|=(unsigned char)READ_SDA;
IIC_SCL=0;
delay_us(2);
}
return receive;
}
(3)24cxx.h
#ifndef __24CXX_H
#define __24CXX_H
#include "myiic.h"
u8 AT24CXX_ReadOneByte(u16 ReadAddr);
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite);
void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite);
void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead);
u8 AT24CXX_Check(void);
void AT24CXX_Init(void);
#endif
(4)24cxx.c
#include "24cxx.h"
#include "delay.h"
void AT24CXX_Init(void)
{
IIC_Init();
}
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{
u8 temp=0;
IIC_Start();
IIC_Send_Byte(0XA0+((ReadAddr/256)<<1));
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr%256);
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(0XA1);
IIC_Wait_Ack();
temp=IIC_Read_Byte();
IIC_Stop();
return temp;
}
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{
IIC_Start();
IIC_Send_Byte(0XA0+((WriteAddr/256)<<1));
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr%256);
IIC_Wait_Ack();
IIC_Send_Byte(DataToWrite);
IIC_Wait_Ack();
IIC_Stop();
delay_ms(10);
}
u8 AT24CXX_Check(void)
{
u8 temp;
temp=AT24CXX_ReadOneByte(255);
if(temp==0X55)return 0;
else
{
AT24CXX_WriteOneByte(255,0X55);
temp=AT24CXX_ReadOneByte(255);
if(temp==0X55)return 0;
}
return 1;
}
void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
{
while(NumToRead)
{
*pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);
NumToRead--;
}
}
void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
{
while(NumToWrite--)
{
AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
WriteAddr++;
pBuffer++;
}
}
(5)main.c
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"
#include "usmart.h"
#include "24cxx.h"
const u8 TEXT_Buffer[]={"helloworld"};
#define SIZE sizeof(TEXT_Buffer)
int main(void)
{
u8 key;
u16 i=0;
u8 datatemp[SIZE];
delay_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(115200);
LED_Init();
LCD_Init();
KEY_Init();
AT24CXX_Init();
POINT_COLOR=RED;
while(AT24CXX_Check());
while(1)
{
key=KEY_Scan(0);
if(key==KEY1_PRES)
{
AT24CXX_Write(0,(u8*)TEXT_Buffer,SIZE);
}
if(key==KEY0_PRES)
{
AT24CXX_Read(0,datatemp,SIZE);
LCD_ShowString(30,190,200,16,16,datatemp);
}
i++;
delay_ms(10);
if(i==20)
{
LED0=!LED0;
i=0;
}
}
}
|