你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32 GPIO模拟I2C程序示例

[复制链接]
STMCU小助手 发布时间:2022-6-16 18:00
01. IIC简介
IIC(Inter-Integrated Circuit)总线是一种由 PHILIPS 公司开发的两线式串行总线,用于连接微控制器及其外围设备。它是由数据线 SDA 和时钟 SCL 构成的串行总线,可发送和接收数据。在 CPU 与被控 IC 之间、IC 与 IC 之间进行双向传送,高速 IIC 总线一般可达 400kbps 以上。

I2C 总线在传送数据过程**有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。

开始信号:SCL 为高电平时,SDA 由高电平向低电平跳变,开始传送数据。
结束信号:SCL 为高电平时,SDA 由低电平向高电平跳变,结束传送数据。
应答信号:接收数据的 IC 在接收到 8bit 数据后,向发送数据的 IC 发出特定的低电平脉冲,表示已收到数据。CPU 向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU 接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。

02. 功能描述
开机的时候先检测24C02是否存在,然后在主循环里面检测两个按键,其中 1 个按键(KEY1)用来执行写入 24C02 的操作,另外一个按键(KEY0)用来执行读出操作,在 TFTLCD 模块上显示相关信息。同时用 DS0 提示程序正在运行。

03. 硬件模块
硬件资源有:
1) 指示灯 DS0
2) KEY_UP 和 KEY1 按键
3) 串口(USMART 使用)
4) TFTLCD 模块
5) 24C02

MMM45TOF36@]79_EXVD22{N.png

04. 软件设计
myiic.h

  1. #ifndef __MYIIC_H
  2. #define __MYIIC_H
  3. #include "sys.h"
  4.                                  
  5. //IO方向设置
  6. #define SDA_IN()  {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=0<<9*2;}        //PB9输入模式
  7. #define SDA_OUT() {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=1<<9*2;} //

  8. //IO操作函数         
  9. #define IIC_SCL    PBout(8) //SCL
  10. #define IIC_SDA    PBout(9) //SDA         
  11. #define READ_SDA   PBin(9)  //输入SDA

  12. //IIC所有操作函数
  13. void IIC_Init(void);                //初始化IIC的IO口                                 
  14. void IIC_Start(void);                                //发送IIC开始信号
  15. void IIC_Stop(void);                                  //发送IIC停止信号
  16. void IIC_Send_Byte(u8 txd);                        //IIC发送一个字节
  17. u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
  18. u8 IIC_Wait_Ack(void);                                 //IIC等待ACK信号
  19. void IIC_Ack(void);                                        //IIC发送ACK信号
  20. void IIC_NAck(void);                                //IIC不发送ACK信号

  21. void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
  22. u8 IIC_Read_One_Byte(u8 daddr,u8 addr);         
  23. #endif
复制代码

myiic.c

  1. #include "myiic.h"
  2. #include "delay.h"

  3. //初始化IIC
  4. void IIC_Init(void)
  5. {                        
  6.           GPIO_InitTypeDef  GPIO_InitStructure;

  7.           RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB时钟

  8.           //GPIOB8,B9初始化设置
  9.           GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
  10.           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
  11.           GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  12.           GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  13.           GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  14.           GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
  15.         IIC_SCL=1;
  16.         IIC_SDA=1;
  17. }
  18. //产生IIC起始信号
  19. void IIC_Start(void)
  20. {
  21.         SDA_OUT();     //sda线输出
  22.         IIC_SDA=1;                    
  23.         IIC_SCL=1;
  24.         delay_us(4);
  25.          IIC_SDA=0;//START:when CLK is high,DATA change form high to low
  26.         delay_us(4);
  27.         IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
  28. }         
  29. //产生IIC停止信号
  30. void IIC_Stop(void)
  31. {
  32.         SDA_OUT();//sda线输出
  33.         IIC_SCL=0;
  34.         IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
  35.          delay_us(4);
  36.         IIC_SCL=1;
  37.         IIC_SDA=1;//发送I2C总线结束信号
  38.         delay_us(4);                                                                  
  39. }
  40. //等待应答信号到来
  41. //返回值:1,接收应答失败
  42. //        0,接收应答成功
  43. u8 IIC_Wait_Ack(void)
  44. {
  45.         u8 ucErrTime=0;
  46.         SDA_IN();      //SDA设置为输入  
  47.         IIC_SDA=1;delay_us(1);           
  48.         IIC_SCL=1;delay_us(1);         
  49.         while(READ_SDA)
  50.         {
  51.                 ucErrTime++;
  52.                 if(ucErrTime>250)
  53.                 {
  54.                         IIC_Stop();
  55.                         return 1;
  56.                 }
  57.         }
  58.         IIC_SCL=0;//时钟输出0            
  59.         return 0;  
  60. }
  61. //产生ACK应答
  62. void IIC_Ack(void)
  63. {
  64.         IIC_SCL=0;
  65.         SDA_OUT();
  66.         IIC_SDA=0;
  67.         delay_us(2);
  68.         IIC_SCL=1;
  69.         delay_us(2);
  70.         IIC_SCL=0;
  71. }
  72. //不产生ACK应答                    
  73. void IIC_NAck(void)
  74. {
  75.         IIC_SCL=0;
  76.         SDA_OUT();
  77.         IIC_SDA=1;
  78.         delay_us(2);
  79.         IIC_SCL=1;
  80.         delay_us(2);
  81.         IIC_SCL=0;
  82. }                                                                              
  83. //IIC发送一个字节
  84. //返回从机有无应答
  85. //1,有应答
  86. //0,无应答                          
  87. void IIC_Send_Byte(u8 txd)
  88. {                        
  89.     u8 t;   
  90.         SDA_OUT();            
  91.     IIC_SCL=0;//拉低时钟开始数据传输
  92.     for(t=0;t<8;t++)
  93.     {              
  94.         IIC_SDA=(txd&0x80)>>7;
  95.         txd<<=1;           
  96.                 delay_us(2);   //对TEA5767这三个延时都是必须的
  97.                 IIC_SCL=1;
  98.                 delay_us(2);
  99.                 IIC_SCL=0;        
  100.                 delay_us(2);
  101.     }         
  102. }            
  103. //读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
  104. u8 IIC_Read_Byte(unsigned char ack)
  105. {
  106.         unsigned char i,receive=0;
  107.         SDA_IN();//SDA设置为输入
  108.     for(i=0;i<8;i++ )
  109.         {
  110.         IIC_SCL=0;
  111.         delay_us(2);
  112.                 IIC_SCL=1;
  113.         receive<<=1;
  114.         if(READ_SDA)receive++;   
  115.                 delay_us(1);
  116.     }                                         
  117.     if (!ack)
  118.         IIC_NAck();//发送nACK
  119.     else
  120.         IIC_Ack(); //发送ACK   
  121.     return receive;
  122. }
复制代码

main.c

  1. #include "sys.h"
  2. #include "delay.h"
  3. #include "usart.h"
  4. #include "led.h"
  5. #include "beep.h"
  6. #include "key.h"
  7. #include "usmart.h"
  8. #include "lcd.h"
  9. #include "rtc.h"
  10. #include "rng.h"
  11. #include "key.h"
  12. #include "wkup.h"
  13. #include "adc.h"
  14. #include "dma.h"
  15. #include "24cxx.h"


  16. //要写入到24c02的字符串数组
  17. const u8 TEXT_Buffer[]={"Explorer STM32F4 IIC TEST"};
  18. #define SIZE sizeof(TEXT_Buffer)         


  19. int main(void)
  20. {
  21.         u8 key;
  22.         u16 i=0;
  23.         u8 datatemp[SIZE];        
  24.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
  25.         delay_init(168);    //初始化延时函数
  26.         uart_init(115200);        //初始化串口波特率为115200
  27.         
  28.         LED_Init();                                        //初始化LED
  29.          LCD_Init();                                        //LCD初始化
  30.         KEY_Init();                                 //按键初始化  
  31.         AT24CXX_Init();                        //IIC初始化
  32.          POINT_COLOR=RED;
  33.         LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");        
  34.         LCD_ShowString(30,70,200,16,16,"IIC TEST");        
  35.         LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
  36.         LCD_ShowString(30,110,200,16,16,"2014/5/6");         
  37.         LCD_ShowString(30,130,200,16,16,"KEY1:Write  KEY0:Read");        //显示提示信息               
  38.          while(AT24CXX_Check())//检测不到24c02
  39.         {
  40.                 LCD_ShowString(30,150,200,16,16,"24C02 Check Failed!");
  41.                 delay_ms(500);
  42.                 LCD_ShowString(30,150,200,16,16,"Please Check!      ");
  43.                 delay_ms(500);
  44.                 LED1=!LED1;//DS0闪烁
  45.         }
  46.         LCD_ShowString(30,150,200,16,16,"24C02 Ready!");   
  47.          POINT_COLOR=BLUE;//设置字体为蓝色        

  48.         while(1)
  49.         {
  50.                 key=Key_Scan();
  51.                 if(key==KEY1_PRESS)//KEY1按下,写入24C02
  52.                 {
  53.                         LCD_Fill(0,170,239,319,WHITE);//清除半屏   
  54.                          LCD_ShowString(30,170,200,16,16,"Start Write 24C02....");
  55.                         AT24CXX_Write(0,(u8*)TEXT_Buffer,SIZE);
  56.                         LCD_ShowString(30,170,200,16,16,"24C02 Write Finished!");//提示传送完成
  57.                 }
  58.                 if(key==KEY0_PRESS)//KEY0按下,读取字符串并显示
  59.                 {
  60.                          LCD_ShowString(30,170,200,16,16,"Start Read 24C02.... ");
  61.                         AT24CXX_Read(0,datatemp,SIZE);
  62.                         LCD_ShowString(30,170,200,16,16,"The Data Readed Is:  ");//提示传送完成
  63.                         LCD_ShowString(30,190,200,16,16,datatemp);//显示读到的字符串
  64.                 }
  65.                 i++;
  66.                 delay_ms(10);
  67.                 if(i==20)
  68.                 {
  69.                         LED1=!LED1;//提示系统正在运行        
  70.                         i=0;
  71.                 }                  
  72.         }            
  73.         
  74. }
复制代码



收藏 评论0 发布时间:2022-6-16 18:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版