标签:
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
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
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
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 }
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
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 }
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
2、工程下载:
http://download.csdn.net/detail/a1181803348/8773845
标签:
原文地址:http://www.cnblogs.com/STM32bo/p/4553116.html