码迷,mamicode.com
首页 > 其他好文 > 详细

17、I2C总线和CAT24WCxx存储器

时间:2015-06-04 22:34:28      阅读:329      评论:0      收藏:0      [点我收藏+]

标签:

1、I2C串行总线概述

I2C总线是PHLIPS公司推出的一种串行总线,是具备多主机系统所需的总线裁决和高低速器件同步功能的高性能串行总线。I2C总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。

技术分享

 

 

2、I2C总线通过上拉电阻接正电源。当总线空闲时,两根线均为高电平。连到总线上的任一器件输出的低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线“与”关系。

技术分享

 

 

3、每个接到I2C总线上的器件都有唯一的地址。主机与其它器件间的数据传送可以是由主机发送数据到其它器件,这时主机即为发送器。由总线上接收数据的器件则为接收器。

     在多主机系统中,可能同时有几个主机企图启动总线传送数据。为了避免混乱, I2C总线要通过总线仲裁,以决定由哪一台主机控制总线。

 

 

4、I2C总线的数据传送

(1) 数据位的有效性规定

I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。

技术分享

(2)起始和终止信号

SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号;SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。 

技术分享

起始和终止信号都是由主机发出的,在起始信号产生后,总线就处于被占用的状态;在终止信号产生后,总线就处于空闲状态。 连接到I2C总线上的器件,若具有I2C总线的硬件接口,则很容易检测到起始和终止信号。 每当发送器件传输完一个字节的数据后,后面必须紧跟一个校验位,这个校验位是接收端通过控制SDA(数据线)来实现的,以提醒发送端数据我这边已经接收完成,数据传送可以继续进行。

(3)数据传送格式

a. 字节传送与应答 每一个字节必须保证是8位长度。

   数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)。

技术分享

由于某种原因从机不对主机寻址信号应答时(如从机正在进行实时性的处理工作而无法接收总线上的数据),它必须将数据线置于高电平,而由主机产生一个终止信号以结束总线的数据传送。

如果从机对主机进行了应答,但在数据传送一段时间后无法继续接收更多的数据时,从机可以通过对无法接收的第一个数据字节的“非应答”通知主机,主机则应发出终止信号以结束数据的继续传送。

当主机接收数据时,它收到最后一个数据字节后,必须向从机发出一个结束传送的信号。这个信号是由对从机的“非应答”来实现的。然后,从机释放SDA线,以允许主机产生终止信号。

b.总线的寻址

I2C总线协议有明确的规定:采用7位的寻址字节(寻址字节是起始信号后的第一个字节)。

寻址字节的位定义

技术分享

D7~D1位组成从机的地址。D0位是数据传送方向位,为“0”时表示主机向从机写数据,为“1”时表示主机由从机读数据。

主机发送地址时,总线上的每个从机都将这7位地址码与自己的地址进行比较,如果相同,则认为自己正被主机寻址,根据R/T位将自己确定为发送器或接收器。

从机的地址由固定部分和可编程部分组成。在一个系统中可能希望接入多个相同的从机,从机地址中可编程部分决定了可接入总线该类器件的最大数目。如一个从机的7位寻址位有4位是固定位,3位是可编程位,这时仅能寻址8个同样的器件,即可以有8个同样的器件接入到该I2C总线系统中。

c.数据帧格式 I2C总线上传送的数据信号是广义的,既包括地址信号,又包括真正的数据信号。

在起始信号后必须传送一个从机的地址(7位),第8位是数据的传送方向位(R/T),用“0”表示主机发送数据(T),“1”表示主机接收数据(R)。

每次数据传送总是由主机产生的终止信号结束。但是,若主机希望继续占用总线进行新的数据传送,则可以不产生终止信号,马上再次发出起始信号对另一从机进行寻址。

 

 

5、在总线的一次数据传送过程中,可以有以下几种组合方式:

(1)、主机向从机发送数据,数据传送方向在整个传送过程中不变:

技术分享

注:有阴影部分表示数据由主机向从机传送,无阴影部分则表示数据由从机向主机传送。A表示应答, A非表示非应答(高电平)。S表示起始信号,P表示终止信号。

(2)、主机在第一个字节后,立即从从机读数据

技术分享

(3)在传送过程中,当需要改变传送方向时,起始信号和从机地址都被重复产生一次,但两次读/写方向位正好反相。

技术分享

 

 

 

 

 

 

6、

技术分享

 

 

 

 

 

 

 

二、CAT24WCxx存储器

 

1、CAT24WCxx存储器的特点

* 与400KHz I2C总线兼容

* 1.8到6.0伏工作电压范围

* 低功耗CMOS技术

* 写保护功能当WP为高电平时进入写保护状态

* 页写缓冲器 * 自定时擦写周期

* 100万次编程/擦除周期

* 可保存数据100年

* 8脚DIP SOIC或TSSOP封装

* 温度范围商业级和工业级

 

 

2、CAT24WCxx存储器概述

CAT24WC01/02/04/08/16是一个1K/2K/4K/8K/16K位串行CMOS,EEPROM内部含有128/256/512/1024/2048个8位字节CATALYST公司的先进CMOS技术实质上减少了器件的功耗,CAT24WC01有一个8字节页写缓冲器CAT24WC02/04/08/16有一个16字节页写缓冲器,该器件通过I2C总线接口进行操作有一个专门的写保护功能

技术分享技术分享

 

 

 

3、引脚说明

技术分享

 

 

4、总线时序

技术分享

 

技术分享

 

 

 

6、写周期时序

技术分享

技术分享

   写周期时间是指从一个写时序的有效停止信号到内部编程/擦除周期结束的这一段时间.在写周期期间,总线接口电路禁能,SDA保持为高电平,器件不响应外部操作。

 

 

 

7、器件寻址

  主器件通过发送一个起始信号启动发送过程,然后发送它所要寻址的从器件的地址。8位从器件地址的高4位固定为(1010)。接下来的3位(A2、A1、A0)为器件的地址位,用来定义哪个器件以及器件的哪个部分被主器件访问,上述8个CAT24WC01/02,4个CAT24WC04,2个CAT24WC08,1个CAT24WC16可单独被系统寻址。从器件8位地址的最低位,作为读写控制位。“1”表示对从器件进行读操作,“0”表示对从器件进行写操作。在主器件发送起始信号和从器件地址字节后,CAT24WC01/02/04/08/16监视总线并当其地址与发送的从地址相符时响应一个应答信号(通过SDA线)。CAT24WC01/02/04/08/16再根据读写控制位(R/W)的状态进行读或写操作。

技术分享

 

 

8、字节写

在字节写模式下,主器件发送起始命令和从器件地址信息(R/W)位置发给从器件,在从器件产生应答信号后,主器件发送CAT24WCxx的字节地址,主器件在收到从器件的另一个应答信号后,再发送数据到被寻址的存储单元。CAT24WCxx再次应答,并在主器件产生停止信号后开始内部数据的擦写,在内部擦写过程中,CAT24WCxx不再应答主器件的任何请求。

技术分享

 

 

9、写 页

用页写,CAT24WC01可一次写入8 个字节数据,CAT24WC02/04/08/16可以一次写入16个字节的数据。页写操作的启动和字节写一样,不同在于传送了一字节数据后并不产生停止信号。主器件被允许发送P(CAT24WC01:P=7;CAT24WC02/04/08/16:P=15)个额外的字节。每发送一个字节数据后CAT24WCxx产生一个应答位并将字节地址低位加1,高位保持不变。 如果在发送停止信号之前主器件发送超过P+1个字节,地址计数器将自动翻转,先前写入的数据被覆盖。 接收到P+1字节数据和主器件发送的停止信号后,CAT24Cxx启动内部写周期将数据写到数据区。所有接收的数据在一个写周期内写入CAT24Cxx。

技术分享

 

10、页写时序

技术分享

 

11、读字节

读操作允许主器件对寄存器的任意字节进行读操作,主器件首先通过发送起始信号、从器件地址和它想读取的字节数据的地址执行一个写操作。在CAT24Cxx应答之后,主器件重新发送起始信号和从器件地址,此时R/W位置1,CAT24Cxx响应并发送应答信号,然后输出所要求的一个8位字节数据,主器件不发送应答信号但产生一个停止信号

技术分享

 

12、顺序读

在CAT24Cxx发送完一个8位字节数据后,主器件产生一个应答信号来响应,告知CAT24Cxx主器件要求更多的数据,对应每个主机产生的应答信号CAT24Cxx将发送一个8位数据字节。当主器件不发送应答信号而发送停止位时结束此操作。

从CAT24Cxx输出的数据按顺序由N到N+1输出。读操作时地址计数器在CAT24Cxx整个地址内增加,这样整个寄存器区域可在一个读操作内全部读出,当读取的字节超过E(对于24WC01,E=127;对24WC02,E=255;对24WC04,E=511;对24WC08,E=1023;对24WC16,E=2047)计数器将翻转到零并继续输出数据字节。

 

13、顺序读时序

技术分享

 

14、典型应用

技术分享

 

 

 

三、例程:

 

1、程序代码:

技术分享
  1 /*************************************************************************************************************************************
  2 *  
  3 *  文件名称:main.c
  4 *  文件功能:主函数文件
  5 *
  6 ***************************************************************************************************************************************/
  7 
  8 #include "pbdata.h"//调用自定义公共函数库
  9 
 10 
 11 /*********************************************************************************
 12 *
 13 * 初始化操作
 14 *
 15 *********************************************************************************/
 16 void RCC_Configuration(void);//系统时钟初始化函数声明
 17 void GPIO_Configuration(void);//GPIO初始化函数声明
 18 void NVIC_Configuration(void);//中断优先级配置函数声明
 19 void USART_Configuration(void);//串口配置函数声明
 20 
 21 
 22 
 23 
 24 /********************************************************************************
 25 *
 26 *  函数名称:main(void)
 27 *  函数功能:主函数
 28 *  函数说明:不能用void定义主函数
 29 *
 30 ********************************************************************************/
 31 int main(void)//void不能void定义主函数
 32 {
 33     u16  dt1=0, dt2=0;    
 34     
 35     RCC_Configuration();    //系统时钟初始化
 36     
 37     GPIO_Configuration();//端口初始化
 38     
 39     USART_Configuration();//串口配置
 40     
 41     NVIC_Configuration();//中断优先级配置
 42     
 43     
 44     
 45   I2C_Init();//I2C初始化
 46   delay_ms(1);//延时1ms才能写
 47 
 48   AT24Cxx_WriteOneByte(0,0x33);//往地址写入字符
 49   dt1=AT24Cxx_ReadOneByte(0);//读出
 50 
 51     AT24Cxx_WriteTwoByte(1,0x1234);//往地址写入字符
 52   dt2=AT24Cxx_ReadTwoByte(1);//读出
 53 
 54     
 55 
 56     
 57     while(1)
 58     {
 59         
 60         printf("dt1=%X\r\n",dt1);//串口打印
 61     printf("dt2=%X\n",dt2);//串口打印
 62         delay_ms(3000);
 63     }
 64     
 65 }
 66     
 67     
 68 
 69 
 70 /********************************************************************************
 71 *
 72 *  函数名称:RCC_Configuration(void)
 73 *  函数功能:系统时钟高初始化函数
 74 *
 75 ********************************************************************************/
 76     void RCC_Configuration(void)//系统时钟高初始化函数
 77   {
 78         
 79     SystemInit();//系统初始化
 80     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//串口对应GPIO时钟使能
 81         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口时钟使能
 82         RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//引脚复用
 83         
 84         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//IIC对应GPIO时钟使能
 85 
 86     }
 87     
 88     
 89 
 90 /*******************************************************************************
 91 *
 92 * 函数名称:GPIO_Configuration(void)
 93 * 函数功能:GPIO初始化函数
 94 *
 95 ********************************************************************************/    
 96     
 97     void GPIO_Configuration(void)//GPIO初始化函数
 98   {
 99               
100         
101 /*串口引脚配置*/
102         GPIO_InitTypeDef GPIO_InitStructure;//定义一个GPIO设置的结构体变量
103 
104 /*输出引脚配置*/        
105         /*结构体变量赋值*/
106       GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;////引脚配置TX
107       GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//配置频率
108         GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//发送要配置成复用推挽输出
109         /*对应的GPIO初始化*/
110       GPIO_Init(GPIOA,&GPIO_InitStructure);
111         
112     
113 /*输入引脚配置*/        
114         /*结构体变量赋值*/
115       GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;////引脚配置RX
116         GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//接收引脚配置成浮空输入
117         /*对应的GPIO初始化*/
118       GPIO_Init(GPIOA,&GPIO_InitStructure);        
119 
120         
121   }
122     
123 
124 /****************************************************************************
125 *
126 *  函数名称:NVIC_Configuration(void)
127 *  函数功能:配置中断优先级
128 *
129 ****************************************************************************/
130     
131 void NVIC_Configuration(void)
132 {
133   NVIC_InitTypeDef NVIC_InitStructure; //定义一个优先级配置结构体变量
134     
135   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//分组
136 
137   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
138   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢断优先级
139   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//响应优先级
140   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能
141     
142   NVIC_Init(&NVIC_InitStructure);//初始化
143 }
144     
145 
146 /*********************************************************************************
147 *
148 *  函数名称:
149 *  函数功能:串口配置函数
150 *
151 *********************************************************************************/
152 void USART_Configuration(void)
153 {
154 /*定义串口配置结构体变量*/
155         USART_InitTypeDef USART_InitStructure;//定义一个串口配置结构体变量
156     
157     
158 /*结构体变量赋值*/
159     USART_InitStructure.USART_BaudRate = 9600;//波特率9600
160     USART_InitStructure.USART_WordLength = USART_WordLength_8b;//位宽,8位
161     USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位1
162     USART_InitStructure.USART_Parity = USART_Parity_No;//不奇偶校验
163     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//流控禁止
164     USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;//发送使能
165 
166     
167 /*发送串口配置初始化*/
168     USART_Init(USART1, &USART_InitStructure);
169     
170 
171 /*打开串口接收中断*/
172       USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//当接收到数据时,会产生中断
173     
174     
175 /*打开串口*/
176     USART_Cmd(USART1,ENABLE);//串口使能,打开
177         
178 /*清空中断标志位*/
179     USART_ClearFlag(USART1,USART_FLAG_TC);
180 }
181     
182     
183     
184     
185     
186 
187     
188     
189 
190     
191 
192     
193     
194     
195     
196     
197     
198     
199     
200     
201     
202     
203     
204     
205     
206     
207     
208     
209     
210     
211     
212     
213     
214     
215     
216     
View Code
技术分享
  1 /****************************************************************************************************************************
  2 *
  3 *  i2c.c
  4 *  I2C通信子函数
  5 *
  6 ****************************************************************************************************************************/
  7 
  8 
  9 
 10 #include "pbdata.h"
 11 
 12 
 13 /*******************************************************************************
 14 *
 15 * 函数名称:I2C_Init(void)
 16 * 函数功能:I2C初始化配置函数
 17 *
 18 ********************************************************************************/    
 19 
 20 void I2C_Init(void)
 21 {
 22 /*串口引脚配置*/
 23      GPIO_InitTypeDef GPIO_InitStructure;//定义一个GPIO设置的结构体变量
 24 
 25 /*输出引脚配置*/        
 26      /*结构体变量赋值*/
 27      GPIO_InitStructure.GPIO_Pin=I2C_SCL|I2C_SDA;////引脚配置
 28      GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//配置频率
 29      GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//配置成推挽输出
 30  
 31 /*对应的GPIO初始化*/
 32      GPIO_Init(GPIOB,&GPIO_InitStructure);
 33 
 34 /*SDA和SCL拉高*/
 35     I2C_SCL_H;
 36     I2C_SDA_H;
 37 
 38 }
 39 
 40 
 41 
 42 
 43 /*******************************************************************************
 44 *
 45 * 函数名称:I2C_SDA_OUT(void)
 46 * 函数功能:I2C输出配置函数
 47 *
 48 ********************************************************************************/    
 49 
 50 void I2C_SDA_OUT(void)
 51 {
 52 /*串口引脚配置*/
 53      GPIO_InitTypeDef GPIO_InitStructure;//定义一个GPIO设置的结构体变量
 54 
 55 /*输出引脚配置*/        
 56      /*结构体变量赋值*/
 57      GPIO_InitStructure.GPIO_Pin=I2C_SDA;////引脚配置
 58      GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//配置频率
 59      GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//配置成推挽输出
 60  
 61 /*对应的GPIO初始化*/
 62      GPIO_Init(GPIOB,&GPIO_InitStructure);
 63 
 64 }
 65 
 66 
 67 
 68 
 69 
 70 /*******************************************************************************
 71 *
 72 * 函数名称:I2C_SDA_IN(void)
 73 * 函数功能:I2C输入配置函数
 74 *
 75 ********************************************************************************/    
 76 
 77 void I2C_SDA_IN(void)
 78 {
 79 /*串口引脚配置*/
 80      GPIO_InitTypeDef GPIO_InitStructure;//定义一个GPIO设置的结构体变量
 81 
 82 /*输出引脚配置*/        
 83      /*结构体变量赋值*/
 84      GPIO_InitStructure.GPIO_Pin=I2C_SDA;////引脚配置
 85      GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//配置成输入上拉
 86  
 87 /*对应的GPIO初始化*/
 88      GPIO_Init(GPIOB,&GPIO_InitStructure);
 89 }
 90 
 91 
 92 
 93 
 94 
 95 /*******************************************************************************
 96 *
 97 * 函数名称:I2C_Start(void)
 98 * 函数功能:产生I2C起始信号
 99 *
100 ********************************************************************************/    
101 
102 void I2C_Start(void)
103 {
104 /*主机发送,所以SDA输出*/
105     I2C_SDA_OUT();
106  
107 /*SDA和SCL拉高*/
108     I2C_SDA_H;
109     I2C_SCL_H;
110 
111 /*延时>4.7us*/
112     delay_us(5);
113 
114 /*SDA拉低*/
115     I2C_SDA_L;
116 
117 /*延时>4.7us*/
118     delay_us(6);
119 
120 /*SCL拉低*/
121     I2C_SCL_L;
122 }
123 
124 
125 
126 
127 
128 /*******************************************************************************
129 *
130 * 函数名称:I2C_Stop(void)
131 * 函数功能:产生I2C停止信号
132 *
133 ********************************************************************************/    
134 
135 void  I2C_Stop(void)
136 {
137 
138 /*主机发送,所以SDA输出*/
139     I2C_SDA_OUT();  
140 
141 /*SDA和SCL拉低*/
142     I2C_SDA_L;
143     I2C_SCL_L;
144 
145 /*SCL拉高*/
146     I2C_SCL_H;
147 
148 /*延时>4.7us*/
149     delay_us(6);
150 
151 /*SDA拉高*/
152     I2C_SDA_H;
153 
154 /*延时>4.7us*/
155     delay_us(6);
156 }
157 
158 
159 
160 
161 
162 /*******************************************************************************
163 *
164 * 函数名称:I2C_Ack(void)
165 * 函数功能:主机产生应答信号ACK
166 *
167 ********************************************************************************/    
168 
169 void  I2C_Ack(void)
170 {  
171 
172 /*SCL拉低*/
173     I2C_SCL_L;
174 
175 /*主机发送,所以SDA输出*/
176     I2C_SDA_OUT();
177 
178 /*SDA拉低*/
179     I2C_SDA_L;
180 
181 /*延时稳定*/
182     delay_us(2);
183 
184 /*SCL拉高*/
185     I2C_SCL_H;
186 
187 /*延时>4.7us*/
188     delay_us(5);
189 
190 /*SCL拉低*/
191     I2C_SCL_L;
192 
193 }
194 
195 
196 
197 
198 
199 
200 /*******************************************************************************
201 *
202 * 函数名称:I2C_NAck(void)
203 * 函数功能:主机产生不应答信号NACK
204 *
205 ********************************************************************************/    
206 
207 void  I2C_NAck(void)
208 {
209  
210 /*SCL拉低*/
211     I2C_SCL_L;
212 
213 /*主机发送,所以SDA输出*/
214     I2C_SDA_OUT();  
215 
216 /*延时稳定*/
217     delay_us(2);
218 
219 /*SDA拉高*/
220     I2C_SDA_H;
221 
222 /*延时>4.7us*/
223     delay_us(5);
224 
225 /*SCL拉低*/
226     I2C_SCL_L;
227 
228 }
229 
230 
231 
232 
233 
234 /*******************************************************************************
235 *
236 * 函数名称:IC2_Wait_Ack(void)
237 * 函数功能:等待从机应答信号,返回1接收应答失败,返回0,接收应答成功
238 *
239 ********************************************************************************/    
240 
241 u8 I2C_Wait_Ack(void)
242 {
243 
244     u8  tempTime=0;
245   
246 /*主机接收,所以SDA输入*/
247     I2C_SDA_IN();
248 
249 /*SDA拉高*/
250     I2C_SDA_H;
251 
252 /*延时稳定*/
253     delay_us(1);
254 
255 /*SCL拉高*/
256     I2C_SCL_H;
257 
258 /*延时稳定*/
259     delay_us(1);
260 
261 /*循环等待*/
262     while(GPIO_ReadInputDataBit(GPIO_I2C,I2C_SDA))
263     {
264        tempTime++;
265        if(tempTime>250) 
266        {
267           I2C_Stop();
268           return 1;
269         }
270      }
271 
272      I2C_SCL_L;
273      return 0;//成功
274 
275 }
276 
277 
278 
279 
280 
281 /*******************************************************************************
282 *
283 * 函数名称:I2C_Send_Byte(u8 txd)
284 * 函数功能:发送数据函数,一个字节
285 *
286 ********************************************************************************/    
287 
288 void  I2C_Send_Byte(u8 txd)
289 {
290    
291     u8 i=0;  
292 
293 /*主机发送,所以SDA输出*/
294     I2C_SDA_OUT(); 
295 
296 /*SCL拉低开始数据传输*/
297     I2C_SCL_L;
298 
299 /*发送一个字节8位*/
300     for(i=0;i<8;i++)
301     {
302       if((txd&0x80)>0)//高位为1时
303           I2C_SDA_H;
304       else
305           I2C_SDA_L;//高位为0时  
306       
307       txd<<=1;//数据左移
308       I2C_SCL_H;//拉高发送数据
309       delay_us(2);//延时稳定
310       I2C_SCL_L;
311       delay_us(2);//延时稳定
312      }
313 }
314 
315 
316 
317 
318 
319 /*******************************************************************************
320 *
321 * 函数名称:I2C_Read_Byte(u8 ack)
322 * 函数功能:读取数据函数,一个字节
323 *
324 ********************************************************************************/    
325 
326 
327 u8  I2C_Read_Byte(u8 ack)
328 {
329   u8 i=0,receive=0;
330 
331 /*主机接收,所以SDA输人*/
332     I2C_SDA_IN();
333 
334     for(i=0;i<8;i++)
335     {
336        I2C_SCL_L;
337        delay_us(2);//延时稳定
338        I2C_SCL_H;
339        receive<<=1;
340 
341        if(GPIO_ReadInputDataBit(GPIO_I2C,I2C_SDA))
342          receive++;
343      
344        delay_us(1);//延时稳定
345      }
346 
347      if(ack==0)
348         I2C_NAck();
349      else
350         I2C_Ack();
351 
352      return receive;
353 }
354 
355 
356 
357     
View Code
技术分享
 1 /****************************************************************************************************************************
 2 *
 3 *  i2c.h
 4 *  I2C通信子函数定义
 5 *
 6 ****************************************************************************************************************************/
 7 
 8 
 9 #ifndef _i2c_H
10 #define _i2C_H
11 
12 #include "pbdata.h"
13 
14 
15 
16 
17 
18 
19 /*******************************************************************************
20 *
21 *  宏定义部分
22 *  方便移植,以后移植,只需改这里
23 *
24 ********************************************************************************/    
25 
26 #define I2C_SCL GPIO_Pin_10  //将10管脚定义I2C_SCL
27 #define I2C_SDA GPIO_Pin_11  //将11管脚定义I2C_SDA
28 #define GPIO_I2C  GPIOB//定义GPIO引脚
29 
30 
31 
32 #define I2C_SCL_H GPIO_SetBits(GPIO_I2C,I2C_SCL)//I2C_SC高电平
33 #define I2C_SCL_L GPIO_ResetBits(GPIO_I2C,I2C_SCL)//I2C_SC低电平
34 
35 #define I2C_SDA_H GPIO_SetBits(GPIO_I2C,I2C_SDA)//I2C_SDA高电平
36 #define I2C_SDA_L GPIO_ResetBits(GPIO_I2C,I2C_SDA)//I2C_SDA低电平
37 
38 
39 
40 
41 
42 /*******************************************************************************
43 *
44 *  子函数声明
45 *
46 ********************************************************************************/    
47 
48 void I2C_Init(void);//I2C初始化配置函数
49 void I2C_SDA_OUT(void);//I2C输出配置函数
50 void I2C_SDA_IN(void);//I2C输入配置函数
51 void I2C_Start(void);//产生I2C起始信号
52 void I2C_Stop(void);//产生I2C停止信号
53 void I2C_Ack(void);//主机产生应答信号ACK
54 void I2C_NAck(void);//主机产生不应答信号NACK
55 u8   I2C_Wait_Ack(void);//等待从机应答信号,返回1接收应答失败,返回0,接收应答成功
56 void I2C_Send_Byte(u8 txd);//发送数据函数
57 u8   I2C_Read_Byte(u8 ack);//读取数据函数
58 
59 
60 
61 #endif
View Code
技术分享
  1 /****************************************************************************************************************
  2 *
  3 * 文件名称:AT24Cxx.c
  4 * 文件功能:AT24Cxx处理函数定义
  5 *
  6 ****************************************************************************************************************/
  7 
  8 
  9 #include "pbdata.h"
 10 
 11 
 12 
 13 
 14 
 15 
 16 /********************************************************************************************
 17 *
 18 * 函数名称:AT24Cxx_ReadOneByte(u16 addr)
 19 * 函数功能:读取一个字节函数
 20 *
 21 ********************************************************************************************/
 22 
 23 u8  AT24Cxx_ReadOneByte(u16 addr)
 24 {
 25    u8 temp=0;
 26    
 27    I2C_Start();//开始I2C
 28 
 29 /*发送器件地址*/
 30    if(EE_TYPE>AT24C016)//AT24C016 之后是双字节寻址
 31    {
 32       I2C_Send_Byte(0xa0);//发送地址
 33       I2C_Wait_Ack();//等待应答
 34       I2C_Send_Byte(addr>>8);//发送数据地址高位
 35     }
 36     else//AT24C16及它之前单字节寻址
 37     {
 38        I2C_Send_Byte(0xa0+((addr/256)<<1));//器件地址+数据地址
 39 
 40      }
 41 
 42        I2C_Wait_Ack();//等待应答
 43        I2C_Send_Byte(addr%256);//双字节发送数据地址低位;单字节是数据地址低位
 44        I2C_Wait_Ack();//等待应答
 45 
 46        I2C_Start();//开始I2C
 47        I2C_Send_Byte(0xa1);//发送起始地址
 48        I2C_Wait_Ack();//等待应答
 49 
 50        temp=I2C_Read_Byte(0);//读取数据,0代表NACK
 51        I2C_Stop();//停止
 52     
 53        return temp;
 54    
 55 }
 56 
 57 
 58 
 59 
 60 /********************************************************************************************
 61 *
 62 * 函数名称:AT24Cxx_WriteOneByte(u16 addr, u8 dt)
 63 * 函数功能:写一个字节函数
 64 *
 65 ********************************************************************************************/
 66 
 67 void  AT24Cxx_WriteOneByte(u16 addr, u8 dt)
 68 {
 69 
 70    I2C_Start();//开始I2C
 71    
 72 /*发送器件地址*/
 73    if(EE_TYPE>AT24C016)//AT24C016 之后是双字节寻址
 74    {
 75       I2C_Send_Byte(0xa0);//发送地址
 76       I2C_Wait_Ack();//等待应答
 77       I2C_Send_Byte(addr>>8);//发送数据地址高位
 78     }
 79     else//AT24C16及它之前单字节寻址
 80     {
 81        I2C_Send_Byte(0xa0+((addr/256)<<1));//器件地址+数据地址
 82 
 83      }
 84 
 85 
 86      I2C_Wait_Ack();//等待应答
 87      I2C_Send_Byte(addr%256);//双字节发送数据地址低位;单字节是数据地址低位
 88      I2C_Wait_Ack();//等待应答
 89 
 90      I2C_Send_Byte(dt);//
 91      I2C_Wait_Ack();//等待应答
 92      I2C_Stop();//停止
 93 
 94      delay_ms(10);
 95 }
 96 
 97 
 98 
 99 
100 
101 
102 
103 /********************************************************************************************
104 *
105 * 函数名称:AT24Cxx_ReadTwoByte(u16 addr)
106 * 函数功能:读取二个字节函数
107 *
108 ********************************************************************************************/
109 
110 u16  AT24Cxx_ReadTwoByte(u16 addr)
111 {
112    u16 temp=0;
113    
114    I2C_Start();//开始I2C
115 
116 /*发送器件地址*/
117    if(EE_TYPE>AT24C016)//AT24C016 之后是双字节寻址
118    {
119       I2C_Send_Byte(0xa0);//发送地址
120       I2C_Wait_Ack();//等待应答
121       I2C_Send_Byte(addr>>8);//发送数据地址高位
122     }
123     else//AT24C16及它之前单字节寻址
124     {
125        I2C_Send_Byte(0xa0+((addr/256)<<1));//器件地址+数据地址
126 
127      }
128 
129        I2C_Wait_Ack();//等待应答
130        I2C_Send_Byte(addr%256);//双字节发送数据地址低位;单字节是数据地址低位
131        I2C_Wait_Ack();//等待应答
132 
133        I2C_Start();//开始I2C
134        I2C_Send_Byte(0xa1);//发送起始地址
135        I2C_Wait_Ack();//等待应答
136 
137        temp=I2C_Read_Byte(1);//读取数据,1代表ACK,继续
138        temp<<=8;
139 
140        temp|=I2C_Read_Byte(0);//读取数据,0代表NACK,结束
141 
142        I2C_Stop();//停止
143     
144        return temp;
145    
146 }
147 
148 
149 
150 
151 
152 
153 
154 /********************************************************************************************
155 *
156 * 函数名称:AT24Cxx_WriteTwoByte(u16 addr, u16 dt)
157 * 函数功能:写二个字节函数
158 *
159 ********************************************************************************************/
160 
161 void  AT24Cxx_WriteTwoByte(u16 addr, u16 dt)
162 {
163 
164    I2C_Start();//开始I2C
165    
166 /*发送器件地址*/
167    if(EE_TYPE>AT24C016)//AT24C016 之后是双字节寻址
168    {
169       I2C_Send_Byte(0xa0);//发送地址
170       I2C_Wait_Ack();//等待应答
171       I2C_Send_Byte(addr>>8);//发送数据地址高位
172     }
173     else//AT24C16及它之前单字节寻址
174     {
175        I2C_Send_Byte(0xa0+((addr/256)<<1));//器件地址+数据地址
176 
177      }
178 
179 
180      I2C_Wait_Ack();//等待应答
181      I2C_Send_Byte(addr%256);//双字节发送数据地址低位;单字节是数据地址低位
182      I2C_Wait_Ack();//等待应答
183 
184      I2C_Send_Byte(dt>>8);
185      I2C_Wait_Ack();//等待应答
186 
187      I2C_Send_Byte(dt&0xff);
188      I2C_Wait_Ack();//等待应答
189      I2C_Stop();//停止
190 
191      delay_ms(10);
192 }
View Code
技术分享
 1 /****************************************************************************************************************
 2 *
 3 * 文件名称:AT24Cxx.h
 4 * 文件功能:AT24Cxx处理函数声明
 5 *
 6 ****************************************************************************************************************/
 7 
 8 
 9 /*防止两次调用头文件错误*/
10 #ifndef _AT24Cxx_H
11 #define _AT24Cxx_H
12 
13 
14 
15 #include "pbdata.h"
16 
17 
18 
19 /********************************************************************************************
20 *
21 * 宏定义部分
22 *
23 ********************************************************************************************/
24 
25 
26 #define  AT24C01      127  
27 #define  AT24C02      255  
28 #define  AT24C04      511  
29 #define  AT24C08      1023 
30 #define  AT24C016     2047  
31 #define  AT24C032     4095  
32 #define  AT24C064     8191  
33 #define  AT24C0128    16383  
34 #define  AT24C0256    32767  
35 
36 #define  EE_TYPE   AT24C02   //型号定义,移植只需改这里
37 
38 
39 
40 
41 /********************************************************************************************
42 *
43 * 函数声明
44 *
45 ********************************************************************************************/
46 
47 u8  AT24Cxx_ReadOneByte(u16 addr);//读取一个字节函数
48 void  AT24Cxx_WriteOneByte(u16 addr, u8 dt);//写一个字节函数
49 
50 u16  AT24Cxx_ReadTwoByte(u16 addr);//读取二个字节函数
51 void  AT24Cxx_WriteTwoByte(u16 addr, u16 dt);//写二个字节函数
52 
53 
54 
55 
56 
57 #endif
View Code
技术分享
  1 /****************************************************************************************************************
  2 *
  3 * 文件名称:pbdata.c
  4 * 文件功能:自定义函数或者全局变量的初始化
  5 *
  6 ****************************************************************************************************************/
  7 
  8 /*头文件声明*/
  9 #include "pbdata.h"
 10 
 11 
 12 
 13 
 14 /********************************************************************************************
 15 *
 16 * 自定义全局变量
 17 *
 18 ********************************************************************************************/
 19 u8 dt=0;
 20 
 21 
 22 
 23 
 24 
 25 /******************************************************************************************
 26 *
 27 * 自定义函数
 28 *
 29 ******************************************************************************************/
 30 
 31 
 32 
 33 /**************************************************
 34 *
 35 *  函数名称:delay_us(u32 nus)
 36 *  函数功能:微秒延时函数
 37 *  输入参数:输入值为延时us
 38 *
 39 ***************************************************/
 40 void delay_us(u32 nus)
 41 {
 42     u32 temp;
 43     SysTick->LOAD = 9*nus;//载入初值,72M/8=9M,也就是1/9us,9*1/9us,所以是执行9次
 44     SysTick->VAL=0X00;//清空计数器,清空后,就自动设置自己设定的计数器的值
 45     SysTick->CTRL=0X01;//使能,减到零动作(不发生中断),采用外部时钟
 46     
 47     do
 48     {
 49           temp=SysTick->CTRL;//标志位,等到一直减到0
 50          }while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达
 51     
 52     SysTick->CTRL=0x00; //关闭计数器
 53     SysTick->VAL =0X00; //清空计数器
 54 }
 55 
 56 
 57 
 58 
 59 
 60 
 61 
 62 /***************************************************
 63 *
 64 * 函数名称:delay_ms(u16 nms)
 65 * 函数功能:毫秒级延时
 66 * 输入参数:输入值位延时ms
 67 *
 68 ****************************************************/
 69 void delay_ms(u16 nms)
 70 {
 71     u32 temp;
 72     SysTick->LOAD = 9000*nms;//载入初值,72M/8=9M,也就是1/9us,9*1/9us,所以是执行9000次
 73     SysTick->VAL=0X00;//清空计数器,清空后,就自动设置自己设定的计数器的值
 74     SysTick->CTRL=0X01;//使能,减到零动作(不发生中断),采用外部时钟
 75     
 76     do
 77     {
 78           temp=SysTick->CTRL;//标志位,等到一直减到0
 79          }while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达
 80     
 81     SysTick->CTRL=0x00; //关闭计数器
 82     SysTick->VAL =0X00; //清空计数器
 83 }
 84 
 85 
 86 
 87 /****************************************************
 88 *
 89 * 重定义printf函数部分
 90 *
 91 ****************************************************/
 92 int fputc(int ch,FILE *F)
 93 {
 94     
 95     USART_SendData(USART1,(u8)ch);
 96     
 97     while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//等待发送完成,判断标志位
 98     
 99     return ch;
100 }
View Code
技术分享
 1 /*pbdata.h*/
 2 /***************************************************************************************************
 3 *
 4 * 文件名称:pbdata.h
 5 * 文件功能:自定义的函数和全局变量的声明头文件
 6 *
 7 ***************************************************************************************************/
 8 
 9 #ifndef _pbdata_H
10 #define _pbdata_H
11 
12 
13 
14 
15 
16 /********************************************************************
17 *
18 *  调用的头文件放在这里
19 *
20 ********************************************************************/
21 #include "stm32f10x.h"
22 #include "misc.h"
23 #include "stm32f10x_exti.h"
24 #include "stm32f10x_tim.h"
25 #include "stm32f10x_usart.h"
26 #include "stdio.h"
27 #include "i2c.h"
28 #include "AT24Cxx.h"
29 
30 
31 /********************************************************************
32 *
33 *  自定义全局变量声明
34 *
35 ********************************************************************/
36 extern u8 dt;
37 
38 
39 
40 
41 
42 /********************************************************************
43 *
44 *  自定义全函数声明
45 *
46 ********************************************************************/
47 void delay(u32 nCount);
48 void delay_us(u32 nus);
49 void delay_ms(u16 nms);
50 int fputc(int ch,FILE *F);
51 
52 
53 
54 #endif
View Code


2、工程下载:

http://download.csdn.net/detail/a1181803348/8773845

 

17、I2C总线和CAT24WCxx存储器

标签:

原文地址:http://www.cnblogs.com/STM32bo/p/4553116.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!