【STM32 标准库】IIC通信

1. STM32 IIC

1.1 IIC简介

1.1.1 IIC物理层

半双工通信:允许双向通信,但同一时刻只能一端发送,不能同时进行;

主从模式:支持多设备通信

总线协议

同步通信

1.1.2 IIC协议层

(1)数据有效性规定

        (2)起始和停止信号

        (3)应答响应

        (4)总线的寻址方式

        (5)数据传输

1.2 AT24C02

2. 软件配置

3. 硬件设计

4. 软件设计

4.1 功能描述

        首先检测 AT24C02 芯片是否存在,如果存在则输出 提示信息,然后通过按键 KEY_UP 和 KEY1 控制 AT24C02 数据读写,并输出写入和 读取的数据信息,最后让 DS0 指示灯闪烁提示系统正常运行。

4.2 软件实现

(1)使能所用 GPIO 端口时钟,初始化 GPIO

(2)使用软件模拟 I2C 通信时序,包含起始和停止信号、应答信号等

(3)编写 AT24C02 读写函数

(4)编写主函数

4.2.1 IIC.c

1.#include "IIC.h"
2.
3.
4.// ---------------------------1.使用IO口模拟IIC时序------------------------------
5./* ---------------------------------函数声明-------------------------------------
6.*函数名称:IIC_Iint
7.*输入参数:无
8.*返回参数:无
9.*功    能:初始化IIC
10.*作    者:lph
11.*日    期:2024/04/27
12.------------------------------------------------------------------------------ */
13.void IIC_Iint(void)
14.{
15.    RCC_APB2PeriphClockCmd(IIC_SCL_PORT_RCC, ENABLE);
16.    RCC_APB2PeriphClockCmd(IIC_SDA_PORT_RCC, ENABLE);
17.    
18.    GPIO_InitTypeDef GPIO_InitStructure;
19.    
20.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
21.    GPIO_InitStructure.GPIO_Pin = IIC_SCL_Pin;
22.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
23.    GPIO_Init(IIC_SCL_PORT, &GPIO_InitStructure);
24.
25.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
26.    GPIO_InitStructure.GPIO_Pin = IIC_SDA_Pin;
27.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
28.    GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
29.    
30.    GPIO_SetBits(IIC_SCL_PORT, IIC_SCL_Pin);    //默认SCL输出高电平
31.    GPIO_SetBits(IIC_SDA_PORT, IIC_SDA_Pin);    //默认SDA输出高电平
32.}
33.
34.
35./* ---------------------------------函数声明-------------------------------------
36.*函数名称:SDA_OUT
37.*输入参数:无
38.*返回参数:无
39.*功    能:SDA输出配置
40.*作    者:lph
41.*日    期:2024/04/27
42.------------------------------------------------------------------------------ */
43.void SDA_OUT(void)
44.{
45.    GPIO_InitTypeDef GPIO_InitStructure;
46.    
47.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
48.    GPIO_InitStructure.GPIO_Pin = IIC_SDA_Pin;
49.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
50.    GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
51.}
52.
53.
54./* ---------------------------------函数声明-------------------------------------
55.*函数名称:SDA_IN
56.*输入参数:无
57.*返回参数:无
58.*功    能:SDA输入配置
59.*作    者:lph
60.*日    期:2024/04/27
61.------------------------------------------------------------------------------ */
62.void SDA_IN(void)
63.{
64.    GPIO_InitTypeDef GPIO_InitStructure;
65.    
66.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
67.    GPIO_InitStructure.GPIO_Pin = IIC_SDA_Pin;
68.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
69.    GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
70.}
71.
72.
73./* ---------------------------------函数声明-------------------------------------
74.*函数名称:IIC_Start
75.*输入参数:无
76.*返回参数:无
77.*功    能:产生IIC起始信号
78.*作    者:lph
79.*日    期:2024/04/27
80.------------------------------------------------------------------------------ */
81.void IIC_Start(void)
82.{
83.    SDA_OUT();   //SDA线输出
84.    GPIO_SetBits(IIC_SCL_PORT,IIC_SCL_Pin);
85.    GPIO_SetBits(IIC_SDA_PORT,IIC_SDA_Pin);
86.    delay_us(5);
87.    GPIO_ResetBits(IIC_SDA_PORT,IIC_SDA_Pin);   //START:当SCL为高,SDA由高变低时
88.    delay_us(6);
89.    GPIO_ResetBits(IIC_SCL_PORT,IIC_SCL_Pin);   //钳住I2C总线,准备发送或接收数据 
90.}
91.
92.
93./* ---------------------------------函数声明-------------------------------------
94.*函数名称:IIC_Start
95.*输入参数:无
96.*返回参数:无
97.*功    能:产生IIC起始信号
98.*作    者:lph
99.*日    期:2024/04/27
100.------------------------------------------------------------------------------ */
101.void IIC_Stop(void)
102.{
103.    SDA_OUT();
104.    GPIO_ResetBits(IIC_SCL_PORT,IIC_SCL_Pin);
105.    GPIO_ResetBits(IIC_SDA_PORT,IIC_SDA_Pin);   //STOP:当SCL为高,SDA由低变高时
106.    GPIO_SetBits(IIC_SCL_PORT,IIC_SCL_Pin);
107.    delay_us(6);
108.    GPIO_SetBits(IIC_SDA_PORT,IIC_SDA_Pin);
109.    delay_us(6);
110.}
111.
112.
113./* ---------------------------------函数声明-------------------------------------
114.*函数名称:IIC_Wait_Ans
115.*输入参数:无
116.*返回参数:u8=1,接收应答失败
117.           u8=0,接收应答成功
118.*功    能:等待应答信号到来
119.*作    者:lph
120.*日    期:2024/04/27
121.------------------------------------------------------------------------------ */
122.u8 IIC_Wait_Ans(void)
123.{
124.    u8 tempTime=0;
125.    
126.    GPIO_SetBits(IIC_SDA_PORT,IIC_SDA_Pin);
127. delay_us(1);
128.    
129.    SDA_IN();   //SDA设置为输入   
130.    GPIO_SetBits(IIC_SCL_PORT,IIC_SCL_Pin);
131.    delay_us(1);
132.    while(READ_SDA)
133.    {
134.        tempTime++;
135.        if(tempTime>250)
136.        {
137.            IIC_Stop();
138.            return 1;   //应答失败
139.        }
140.    }
141.    GPIO_ResetBits(IIC_SCL_PORT,IIC_SCL_Pin);
142.    return 0;   //应答成功
143.}
144.
145.
146./* ---------------------------------函数声明-------------------------------------
147.*函数名称:IIC_Ans
148.*输入参数:无
149.*返回参数:无
150.*功    能:产生Ans应答信号
151.*作    者:lph
152.*日    期:2024/04/27
153.------------------------------------------------------------------------------ */
154.//应答信号
155.void IIC_Ans(void)
156.{
157.    GPIO_ResetBits(IIC_SCL_PORT,IIC_SCL_Pin);
158.    SDA_OUT();
159.    GPIO_ResetBits(IIC_SDA_PORT,IIC_SDA_Pin);
160.    delay_us(2);
161.    GPIO_SetBits(IIC_SCL_PORT,IIC_SCL_Pin);
162.    delay_us(5);
163.    GPIO_ResetBits(IIC_SCL_PORT,IIC_SCL_Pin);
164.}
165.
166.
167./* ---------------------------------函数声明-------------------------------------
168.*函数名称:IIC_NoneAns
169.*输入参数:无
170.*返回参数:无
171.*功    能:产生NoneAns非应答信号
172.*作    者:lph
173.*日    期:2024/04/27
174.------------------------------------------------------------------------------ */
175.//非应答信号
176.void IIC_NoneAns(void)
177.{
178.    GPIO_ResetBits(IIC_SCL_PORT,IIC_SCL_Pin);
179.    SDA_OUT();
180.    GPIO_SetBits(IIC_SDA_PORT,IIC_SDA_Pin);
181.    delay_us(2);
182.    GPIO_SetBits(IIC_SCL_PORT,IIC_SCL_Pin);
183.    delay_us(5);
184.    GPIO_ResetBits(IIC_SCL_PORT,IIC_SCL_Pin);
185.}
186.
187.
188./* ---------------------------------函数声明-------------------------------------
189.*函数名称:IIIC_SendByte
190.*输入参数:u8 txd:字节数据
191.*返回参数:无
192.*功    能:IIC发送一个字节的数据
193.*作    者:lph
194.*日    期:2024/04/27
195.------------------------------------------------------------------------------ */
196.void IIC_SendByte(u8 txd)
197.{
198.    u8 i=0;
199.    
200.    SDA_OUT();
201.    GPIO_ResetBits(IIC_SCL_PORT,IIC_SCL_Pin);   //拉低时钟开始数据传输
202.    for(i=0;i<8;i++)
203.    {
204.        if((txd&0x80)>0)  //判断最高位是否为1
205.            GPIO_SetBits(IIC_SDA_PORT,IIC_SDA_Pin);
206.        else
207.            GPIO_ResetBits(IIC_SDA_PORT,IIC_SDA_Pin);
208.        
209.        txd<<=1;
210.        delay_us(2);
211.        GPIO_SetBits(IIC_SCL_PORT,IIC_SCL_Pin);
212.        delay_us(2);
213.        GPIO_ResetBits(IIC_SCL_PORT,IIC_SCL_Pin);
214.    }
215.}
216.
217.
218./* ---------------------------------函数声明-------------------------------------
219.*函数名称:IIC_ReadByte
220.*输入参数:u8 ans:是否应答?
221.            ans=1,发送Ans
222.            ans=0,发送NoneAns
223.*返回参数:无
224.*功    能:IIC读一个字节的数据
225.*作    者:lph
226.*日    期:2024/04/27
227.------------------------------------------------------------------------------ */
228.u8 IIC_ReadByte(u8 ans)
229.{
230.    u8 i=0;
231.    u8 receive=0;
232.    
233.    SDA_IN();
234.    
235.    for(i=0;i<8;i++)
236.    {
237.        GPIO_ResetBits(IIC_SCL_PORT,IIC_SCL_Pin);
238.        delay_us(2);
239.        GPIO_SetBits(IIC_SCL_PORT,IIC_SCL_Pin);
240.        receive<<=1;
241.        if(READ_SDA==1)
242.            receive++;
243.        delay_us(1);
244.    }
245.    if(!ans)
246.        IIC_NoneAns();
247.    else
248.        IIC_Ans();
249.    return receive;
250.}

4.2.2 IIC.h

1.#ifndef __IIC_H
2.#define __IIC_H
3.
4.#include "system.h"
5.#include "SysTick.h"
6.
7.#define IIC_SCL_PORT        GPIOB
8.#define IIC_SCL_Pin         GPIO_Pin_6
9.#define IIC_SCL_PORT_RCC    RCC_APB2Periph_GPIOB
10.
11.#define IIC_SDA_PORT        GPIOB
12.#define IIC_SDA_Pin         GPIO_Pin_7
13.#define IIC_SDA_PORT_RCC    RCC_APB2Periph_GPIOB
14.
15.// GPIO位带操作
16.#define IIC_SCL             PBout(6)
17.#define IIC_SDA             PBout(7)
18.#define READ_SDA            PBin(7)
19.
20.void IIC_Iint(void);
21.void SDA_OUT(void);
22.void SDA_IN(void);
23.void IIC_Start(void);
24.void IIC_Stop(void);
25.void IIC_Ans(void);
26.void IIC_NoneAns(void);
27.void IIC_SendByte(u8 txd);
28.u8 IIC_ReadByte(u8 ans);
29.u8 IIC_Wait_Ans(void);
30.
31.#endif

4.2.3 AT24Cxx.c

1.#include "AT24Cxx.h"
2.
3.
4./* ---------------------------------函数声明-------------------------------------
5.*函数名称:AT24Cxx_Iint
6.*输入参数:无
7.*返回参数:无
8.*功    能:AT24CXX初始化
9.*作    者:lph
10.*日    期:2024/04/27
11.------------------------------------------------------------------------------ */
12.void AT24Cxx_Iint(void)
13.{
14.    IIC_Iint();
15.}
16.
17.
18./* ---------------------------------函数声明-------------------------------------
19.*函数名称:AT24Cxx_WriteOneByte
20.*输入参数:WriteAddr:写入数据的目的地址 
21.     DataToWrite:要写入的数据
22.*返回参数:无
23.*功    能:在AT24CXX指定地址写入一个数据
24.*作    者:lph
25.*日    期:2024/04/27
26.------------------------------------------------------------------------------ */
27.void AT24Cxx_WriteOneByte(u8 WriteAdder,u8 data)
28.{
29.    IIC_Start();
30.    
31.    if(EE_TYPE>AT24C16)
32. {
33.  IIC_SendByte(0XA0);     //发送写命令
34.  IIC_Wait_Ans();
35.  IIC_SendByte(WriteAdder>>8);//发送高地址   
36. }
37.    else 
38. {
39.  IIC_SendByte(0XA0+((WriteAdder/256)<<1));   //发送器件地址0XA0,写数据
40. }   
41.    
42. IIC_Wait_Ans();    
43.    IIC_SendByte(WriteAdder%256);   //发送低地址
44. IIC_Wait_Ans(); 
45.    
46. IIC_SendByte(data);     //发送字节          
47. IIC_Wait_Ans();  
48.    
49.    IIC_Stop();//产生一个停止条件 
50. delay_ms(10); 
51.    
52.}
53.
54.
55./* ---------------------------------函数声明-------------------------------------
56.*函数名称:AT24Cxx_ReadOneByte
57.*输入参数:ReadAddr:开始读数的地址 
58.*返回参数:无
59.*功    能:在AT24CXX指定地址读出一个数据
60.*作    者:lph
61.*日    期:2024/04/27
62.------------------------------------------------------------------------------ */
63.u8 AT24Cxx_ReadOneByte(u8 ReadAdder)
64.{
65.    u8 temp=0;
66.    
67.    IIC_Start();
68.    
69.    if(EE_TYPE>AT24C16)
70.    {
71.        IIC_SendByte(0XA0);  //器件地址
72.        IIC_Wait_Ans();
73.        IIC_SendByte(ReadAdder>>8);//发送高地址
74.    }
75.    else 
76. {
77.  IIC_SendByte(0XA0+((ReadAdder/256)<<1));   //发送器件地址0XA0,写数据
78. } 
79.    
80.    IIC_Wait_Ans();
81.    IIC_SendByte(ReadAdder%256);
82.    IIC_Wait_Ans();
83.    
84.    IIC_Start();
85.    IIC_SendByte(0XA1);  ////进入接收模式
86.    IIC_Wait_Ans();
87.    
88.    temp=IIC_ReadByte(0);
89.    
90.    IIC_Stop();
91.    return temp;
92.}
93.
94.
95./* ---------------------------------函数声明-------------------------------------
96.*函数名称:AT24Cxx_WriteLenByte
97.*输入参数:WriteAddr:写入数据的目的地址 
98.  DataToWrite:要写入的数据
99.  Len:要写入数据的长度2,4
100.*返回参数:无
101.*功    能:在AT24CXX里面的指定地址开始写入长度为Len的数据,用于写入16bit或者32bit的数据
102.*作    者:lph
103.*日    期:2024/04/27
104.------------------------------------------------------------------------------ */
105.void AT24Cxx_WriteLenByte(u16 WriteAdder,u32 DataToWrite,u8 Len)
106.{   
107. u8 t;
108. for(t=0;t<Len;t++)
109. {
110.  AT24Cxx_WriteOneByte(WriteAdder+t,(DataToWrite>>(8*t))&0xff);
111. }                
112.}
113.
114.
115./* ---------------------------------函数声明-------------------------------------
116.*函数名称:AT24Cxx_ReadLenByte
117.*输入参数:ReadAddr:开始读出的地址 
118.  Len:要读出数据的长度2,4
119.*返回参数:无
120.*功    能:在AT24CXX里面的指定地址开始读出长度为Len的数据,用于读出16bit或者32bit的数据
121.*作    者:lph
122.*日    期:2024/04/27
123.------------------------------------------------------------------------------ */
124.u32 AT24Cxx_ReadLenByte(u16 ReadAdder,u8 Len)
125.{   
126. u8 t;
127. u32 temp=0;
128. for(t=0;t<Len;t++)
129. {
130.  temp<<=8;
131.  temp+=AT24Cxx_ReadOneByte(ReadAdder+Len-t-1);          
132. }
133. return temp;                
134.}
135.
136.
137./* ---------------------------------函数声明-------------------------------------
138.*函数名称:AT24Cxx_Check
139.*输入参数:无
140.*返回参数:u8=1,自检失败
141.           u8=0,自检成功
142.*功    能:检查AT24CXX是否正常
143.*作    者:lph
144.*日    期:2024/04/27
145.------------------------------------------------------------------------------ */
146.u8 AT24Cxx_Check(void)
147.{
148.    u8 temp=0;
149.    
150.    temp=AT24Cxx_ReadOneByte(255);
151.    if(temp==0x36)
152.        return 0;
153.    else
154.    {
155.        AT24Cxx_WriteOneByte(255,0x36);
156.        temp=AT24Cxx_ReadOneByte(255);
157.        if(temp==0x36)
158.            return 0;
159.    }
160.    return 1;
161.}
162.
163.
164./* ---------------------------------函数声明-------------------------------------
165.*函数名称:AT24Cxx_Read
166.*输入参数:ReadAddr:开始读出的地址 对24c02为0~255
167.        pBuffer:数据数组首地址
168.        NumToRead:要读出数据的个数
169.*返回参数:无
170.*功    能:在AT24CXX里面的指定地址开始读出指定个数的数据
171.*作    者:lph
172.*日    期:2024/04/27
173.------------------------------------------------------------------------------ */
174.void AT24Cxx_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
175.{
176. while(NumToRead)
177. {
178.  *pBuffer++=AT24Cxx_ReadOneByte(ReadAddr++); 
179.  NumToRead--;
180. }
181.} 
182.
183.
184./* ---------------------------------函数声明-------------------------------------
185.*函数名称:AT24Cxx_Write
186.*输入参数:WriteAddr:开始写入的地址 对24c02为0~255
187.  pBuffer:数据数组首地址
188.  NumToRead:要读出数据的个数
189.*返回参数:无
190.*功    能:在AT24CXX里面的指定地址开始写入指定个数的数据
191.*作    者:lph
192.*日    期:2024/04/27
193.------------------------------------------------------------------------------ */
194.void AT24Cxx_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
195.{
196. while(NumToWrite--)
197. {
198.  AT24Cxx_WriteOneByte(WriteAddr,*pBuffer);
199.  WriteAddr++;
200.  pBuffer++;
201. }
202.}
203.

4.2.4 AT24Cxx.h

1.#ifndef __AT24Cxx_H
2.#define __AT24Cxx_H
3.
4.#include "system.h"
5.#include "IIC.h"
6.#include "SysTick.h"
7.
8.#define AT24C01  127
9.#define AT24C02  255
10.#define AT24C04  511
11.#define AT24C08  1023
12.#define AT24C16  2047
13.#define AT24C32  4095
14.#define AT24C64     8191
15.#define AT24C128 16383
16.#define AT24C256 32767  
17.
18.//开发板使用的是24c02,所以定义EE_TYPE为AT24C02
19.#define EE_TYPE AT24C02
20.
21.void AT24Cxx_Iint(void);
22.void AT24Cxx_WriteOneByte(u8 WriteAdder,u8 data);
23.u8 AT24Cxx_ReadOneByte(u8 ReadAdder);
24.void AT24Cxx_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len);
25.u32 AT24Cxx_ReadLenByte(u16 ReadAdder,u8 Len);
26.u8 AT24Cxx_Check(void);
27.void AT24Cxx_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead);
28.void AT24Cxx_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite);
29.
30.#endif

4.2.5 main.c

1./* Includes ------------------------------------------------------------------*/
2.#include "system.h"
3.#include "LED.h"
4.#include "SysTick.h"
5.#include "USART.h"
6.#include "IIC.h"
7.#include "AT24Cxx.h"
8.#include "KEY.h"
9.
10./* 主函数main() --------------------------------------------------------------*/
11.int main()
12.{   
13.    // 自定义变量
14.    u8 i=0;
15.    u8 key=0;
16.    u8 input_data=0;
17.    u8 output_data=0;
18.    // 初始化
19.    SysTick_Iint(72);
20.    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中断优先级分组 分2组
21.    LED_Init();
22.    USART1_Iint(115200);
23.    KEY_Iint();
24.    AT24Cxx_Iint();
25.    
26.    while(AT24Cxx_Check())
27.    {
28.        printf("AT24Cxx检测不正常!\r\n");
29.        delay_ms(500);
30.    }
31.    printf("AT24Cxx检测正常!\r\n");
32.    
33.    
34.    while(1)
35.    {
36.       key=KEY_Scan(0);
37.       if(key==KEY_UP_PRESS)
38.       {
39.           input_data++;
40.           if(input_data>255)
41.               input_data=255;
42.           AT24Cxx_WriteOneByte(0,input_data);
43.           printf("写入数据为:%d\r\n",input_data);
44.       }
45.       else if(key==KEY0_PRESS)
46.       {
47.           output_data=AT24Cxx_ReadOneByte(0);
48.           printf("读取数据为:%d\r\n",output_data);
49.       }
50.       
51.        i++;
52.  if(i%20==0)
53.  {
54.   LED0=!LED0;
55.  }
56.  
57.  delay_ms(10);
58.    }
59.}

4.3 实验结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值