i2c芯片的驱动程序(汇编)

合集下载

51单片机的I2C底层驱动程序(IO口模拟)

51单片机的I2C底层驱动程序(IO口模拟)

51单片机的I2C底层驱动程序(IO口模拟)/*Title:I2C for 80C51Author:yuyouliang51单片机(本人使用STC89C52单片机,12T模式)的I2C驱动程序,使用逻辑分析仪对该协议进行分析,发现波形比较美观,SCL 的频率在70KHz左右(11.0592M晶振),低于标准的100K,可以适应大多数的I2C器件。

如果感觉速度过快或过慢,可以自行修改延时。

希望可以给读者一个参考,给读者一些帮助!*//*i2c.h文件 */#ifndef __I2C_H_#define __I2C_H_sbit SCL = P2^1;sbit SDA = P2^0;void start_i2c(); //启动I2C总线:SCL高电平期间,SDA由高变低void stop_i2c(); //停止I2C总线:SCL高电平期间,SDA由低变高void send_i2c(unsigned char c); //主机发送一个字节,先发送最高位unsigned char receive_i2c(); //主机接收一个字节,先接收最高位void master_ack(bit ack); //主机非应答信号(填参数0)或应答信号(填参数1)void slave_ack(); //等待从机应答信号#endif/* i2c.c文件 */#include#include#include#define nop() _nop_()void start_i2c() //启动I2C总线:SCL高电平期间,SDA由高变低{SDA=1;SCL=1;nop();nop();nop();nop();SDA=0;SCL=0;}void stop_i2c() //停止I2C总线,SCL高电平期间,SDA由低变高{SDA=0;SCL=1;nop();nop();nop();nop();SDA=1;}void slave_ack() //等待从机应答信号,如果从机迟迟没有应答,则结束总线。

I2C总线AT24C01读写程序(汇编和C)

I2C总线AT24C01读写程序(汇编和C)
SETB SCL
NOP
NOP
MOV C,SDA
RLC A
CLR SCL
DJNZ B,I2C_RECEIVE8IT_A
RET
C语言写的24C01 单字节读写程序
LCALL I2C_SEND8BIT
LCALL I2C_ACK
JC I2C_READ_A ;=1,表示无确认,再次发送
MOV A,Address
LCALL I2C_SEND8BIT
LCALL I2C_ACK
unsigned char i2c_read(unsigned char Address)
{
unsigned char c;
do{
i2c_start();
i2c_send8bit(0xA0);
}while(i2c_ack()); //=1,表示无确认,再次发送
; 24C01存储器I2C总线实验 汇编语言例子
; =======================================================
SDA EQU P2.0
SCL EQU P2.1
i2c_write(地址,数据),写一个字节
=======================================================*/
void i2c_write(unsigned char Address,unsigned char Data)
{
do{
I2C总线AT24C01读写程序(汇编和C)
--------------------------------------------------------------------------------

i2c_rtc_rx8025驱动总结

i2c_rtc_rx8025驱动总结

ARM : at91-sam9x5ekLinux内核:linux-2.6.39时钟芯片:rx8025 SA/NB第一种方法:Rx8025驱动程序在该linux内核中已经包含,路径为:drivers/rtc/rtc-rx8025.c所以在内核中增加驱动只需要配置即可:1.执行make ARCH=arm menuconfig 进入菜单选项,选择RTC配置,选中EPSONRX-8025SA/NB,同时一定要去掉cpu自带的时钟。

2.i2c support 需要选中I2C Hardware Bus support中GPIO-based bitbanging I2C,否则,即使rtc驱动正确,也不能使用,提示:drivers/rtc/hctosys.c: unable to open rtc device (rtc0)。

问题源自,驱动配置正确,I2C驱动没有加载正确,udevd不能创建rtc0设备节点3.在arch/arm/mach-at91/board-sam9x5ek.c中添加信息,注意此处的name名称要与驱动程序中id_table中的名称保持一致。

而在linux某些匹配机制中,设备名称是与驱动名称相一致。

如果名称不能正确匹配,系统是不会执行probe函数的。

另外需要注意的是i2c地址,手册上给出的地址一般都是带有读写位的,而程序中的地址需要把最后一位的读写位去掉,取前面的7位。

Rx8025的地址为0x64,相应的程序中的地址应该为0x32。

否则会提示对寄存器的操作失败。

4.驱动正确配置后,生成相应的文件/dev/i2c-0/dev/rtc0/sys/bus/i2c/drivers/rtc-rx8025/sys/bus/i2c/drivers/0-0032。

24LC65 I2C EEPROM字节读写驱动程序

24LC65 I2C EEPROM字节读写驱动程序

24LC65 I2C EEPROM字节读写驱动程序[龙啸九天] [786次] 01-3-24 下午07:54:15/*————————————————————〖说明〗24LC65 I2C EEPROM字节读写驱动程序,芯片A0-A1-A2要接VCC。

现缺页写、页读,和CRC校验程序。

以下程序经过50台验证,批量的效果有待考察。

为了安全起见,程序中很多NOP是冗余的,希望读者能进一步精简,但必须经过验证。

51晶振为11.0592MHz〖文件〗24LC65.c ﹫2001/03/23〖作者〗龙啸九天 c51@ <a href= target=_blank></a> 〖修改〗修改建议请到论坛公布 <a href= target=_blank></a> 〖版本〗V1.00A Build 0323—————————————————————*/#define SDA P0_0#define SCL P0_1/*----------------------------------------------------------------------------调用方式:write_8bit(uchar ch) ﹫2001/03/23函数说明:内函数,私有,用户不直接调用。

------------------------------------------------------------------------------*/write_8bit(uchar ch){uchar i=8;SCL=0;_nop_();_nop_();_nop_();_nop_();_nop_();while (i--){SDA=(bit)(ch&0x80);_nop_();_nop_();_nop_();_nop_();_nop_();ch<<=1;SCL=1;_nop_();_nop_();_nop_();_nop_();_nop_();SCL=0;_nop_();_nop_();_nop_();_nop_();_nop_();}_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}/*--------------------------------------------------------------------------------调用方式:void ACK(void) ﹫2001/03/23函数说明:内函数,私有,用户不直接调用。

I2C_周立功标准驱动程序_c代码

I2C_周立功标准驱动程序_c代码

I2C_周立功标准驱动程序_c代码1. /****************************************Copyright(c)**************************************************2. ** 广州周立功单片机发展有限公司3. ** 研究所4. ** 产品一部5. **6. **7. **8. **--------------文件信息--------------------------------------------------------------------------------9. **文件名: I2c.c10. **创建人: 陈明计11. **最后修改日期: 2003年7月21日12. **描述: μCOS-II下LPC210x的I2c主模式底层驱动 13. **14. **--------------历史版本信息----------------------------------------------------------------------------15. ** 创建人: 陈明计16. ** 版本: v1.017. ** 日期: 2003年7月8日18. ** 描述: 原始版本19. **20. **------------------------------------------------------------------------------------------------------21. ** 修改人: 陈明计22. ** 版本: v1.123. ** 日期: 2003年7月21日24. ** 描述: 根据正式文档更改寄存器名25. **26. **--------------当前版本修订------------------------------------------------------------------------------27. ** 修改人:28. ** 日期:29. ** 描述:30. **31. **------------------------------------------------------------------------------------------------------32.************************************************************************ ********************************/33.34. #define IN_I2C35. #include "config.h"36. static uint8 *I2cBuf;37. static OS_EVENT *I2cSem;38. static OS_EVENT *I2cMbox;39. static int16 I2cNbyte;40. static uint8 I2cAddr;41.42. #define I2C_WRITE_END 1 /* 写完成 */ 43. #define I2C_READ_END 2 /* 读完成 */ 44. #define I2C_NOT_GET_BUS 4 /* 丢失仲裁 */ 45. #define I2C_ACK_ERR 8 /* 接收ACK错误 */46.47.48./*********************************************************************** **********************************49. ** 函数名称: I2cInit50. ** 功能描述: 初始化I2c(主模式)51. ** 输入: FI2c:I2c总线频率52. **53. ** 输出:TRUE :成功54. ** FALSE:失败55. ** 全局变量: I2cSem,I2cMbox56. ** 调用模块: OSSemCreate57. **58. ** 作者: 陈明计59. ** 日期: 2003年7月8日60. **-------------------------------------------------------------------------------------------------------61. ** 修改人: 陈明计62. ** 日期: 2003年7月10日63. **-------------------------------------------------------------------------------------------------------64. ** 修改人: 陈明计65. ** 日期: 2003年7月21日66. **------------------------------------------------------------------------------------------------------67.************************************************************************ ********************************/68. uint8 I2cInit(uint32 FI2c)69. {70. VICIntEnClr = 1 << 9; /* 禁止能I2c中断 */ 71. if (FI2c <= 400000)72. {73. PINSEL0 = (PINSEL0 & 0xffffff0f) | 0x50; /* 选择管脚为I2c */ 74. I2CONCLR = 0x6C; /* 清除控制寄存器 */ 75. I2SCLH = (Fpclk / FI2c + 1) / 2; /* 设置高电平时间 */ 76. I2SCLL = (Fpclk / FI2c) / 2; /* 设置低电平时间 */ 77. I2cSem = OSSemCreate(1); /* 信号量用于互斥操作总线 */ 78.I2cMbox = OSMboxCreate(NULL); /* 消息邮箱用于中断向任务传递操作结果 */79. if (I2cMbox == NULL)80. {81. return FALSE;82. }83. if (I2cSem != NULL)84. {85. return TRUE;86. }87. }88. return FALSE;89. }90.91./*********************************************************************** **********************************92. ** 函数名称: __I2cWrite93. ** 功能描述: 读I2C,但不发送STOP信号94. ** 输入: Addr:从机地址95. ** Data:将要写的数据96. ** 写的数据数目97. ** 输出:发送的数据字节数98. **99. ** 全局变量: I2cAddr,I2cNbyte,I2cBuf100. ** 调用模块: OSMboxPend101. **102. ** 作者: 陈明计103. ** 日期: 2003年7月8日104. **-------------------------------------------------------------------------------------------------------105. ** 修改人: 陈明计106. ** 日期: 2003年7月21日107. **------------------------------------------------------------------------------------------------------108.************************************************************************ ********************************/109. uint8 __I2cWrite(uint8 Addr, uint8 *Data, int16 NByte) 110. { 111. uint8 err;112. unsigned int Rt;113.114. I2cAddr = Addr & 0xfe; /* 存储发送地址 */ 115. I2cNbyte = NByte; /* 存储写字节数 */ 116. I2cBuf = Data; /* 存储写的数据的指针 */ 117.I2CONSET = 0x24; /* 设置为主机,并启动总线 */ 118.119. Rt = (unsigned int) OSMboxPend(I2cMbox, 0, &err); /* 等待操作结束 */ 120. return Rt;121. }122.123.124./*********************************************************************** **********************************125. ** 函数名称: I2cWrite126. ** 功能描述: 向I2C从器件写数据127. ** 输入: Addr:从机地址128. ** Data:指向将要写的数据的指针129. ** NByte:写的数据数目130. ** 输出:发送的数据字节数131. **132. ** 全局变量: I2cSem,I2cNbyte133. ** 调用模块: OSSemPend,__I2cWrite,OSSemPost134. **135. ** 作者: 陈明计136. ** 日期: 2003年7月8日137. **-------------------------------------------------------------------------------------------------------138. ** 修改人: 陈明计139. ** 日期: 2003年7月10日140. **-------------------------------------------------------------------------------------------------------141. ** 修改人: 陈明计142. ** 日期: 2003年7月21日143. **------------------------------------------------------------------------------------------------------144.************************************************************************ ********************************/145. uint16 I2cWrite(uint8 Addr, uint8 *Data, int16 NByte) 146. {147. uint8 err;148.149. OSSemPend(I2cSem, 0, &err);150.151. I2CONCLR = 0x6C;152. I2CONSET = 0x40; /* 使能I2c */ 153. VICIntEnable = 1 << 9; /* 使能I2c中断 */ 154.155. if (__I2cWrite(Addr, Data, NByte) == I2C_WRITE_END) 156. { 157. I2CONSET = 1 << 4; /* 发送停止信号 */ 158. I2CONCLR = 0x28; /* 清除标志 */ 159. }160.161. VICIntEnClr = 1 << 9; /* 禁止能I2c中断 */ 162.163. OSSemPost(I2cSem);164. return (NByte - I2cNbyte);165. }166.167./*********************************************************************** **********************************168. ** 函数名称: I2cRead169. ** 功能描述: 从I2c从器件读数据170. ** 输入: Addr:从机地址171. ** Ret:指向返回数据存储位置的指针172. ** Eaddr:扩展地址存储位置173. ** EaddrNByte:扩展地址字节数,0为无174. ** ReadNbyte:将要读取的字节数目175. ** 输出:已读取的字节数176. **177. ** 全局变量: I2cSem,I2cAddr,I2cNbyte,I2cBuf178. ** 调用模块: OSSemPend,__I2cWrite,OSMboxPend,OSSemPost 179. ** 180. ** 作者: 陈明计181. ** 日期: 2003年7月8日182. **-------------------------------------------------------------------------------------------------------183. ** 修改人: 陈明计184. ** 日期: 2003年7月21日185. **------------------------------------------------------------------------------------------------------186.************************************************************************ ********************************/187. int16 I2cRead(uint8 Addr, uint8 *Ret, uint8 *Eaddr, int16 EaddrNByte, int16 ReadNbyte)188. {189. uint8 err;190.191. OSSemPend(I2cSem, 0, &err);192.193. I2CONCLR = 0x6C;194. I2CONSET = 0x40; /* 使能I2c */ 195. VICIntEnable = 1 << 9; /* 使能I2c中断 */ 196.197. if (EaddrNByte > 0)198. {199. if (__I2cWrite(Addr, Eaddr, EaddrNByte) != I2C_WRITE_END) 200. {201. return -1;202. }203. }204.205. I2cAddr = Addr | 0x01; /* 存储发送地址 */ 206. I2cNbyte = ReadNbyte; /* 存储读字节数 */ 207. I2cBuf = Ret; /* 存储读到的数据 */ 208. I2CONCLR = 0x28;209. I2CONSET = 0x24; /* 设置为主机,并启动总线 */ 210. VICIntEnable = 1 << 9; /* 使能I2c中断 */ 211.212. OSMboxPend(I2cMbox, 0, &err); /* 等待操作结束 */ 213.214. VICIntEnClr = 1 << 9; /* 禁止能I2c中断 */ 215.OSSemPost(I2cSem);216. return (ReadNbyte - I2cNbyte);217. }218.219.220./*********************************************************************** **********************************221. ** 函数名称: I2c_Exception222. ** 功能描述: I2c中断服务程序223. ** 输入: 无224. **225. ** 输出: 无226. **227. ** 全局变量: I2cAddr,I2cBuf,I2cNbyte,I2cMbox228. ** 调用模块: OSMboxPost229. **230. ** 作者: 陈明计231. ** 日期: 2003年7月8日232. **-------------------------------------------------------------------------------------------------------233. ** 修改人: 陈明计234. ** 日期: 2003年7月21日235. **------------------------------------------------------------------------------------------------------236.************************************************************************ ********************************/237. void I2c_Exception(void)238. {239. OS_ENTER_CRITICAL();240. switch(I2STAT & 0xf8)241. {242. case 0x08: /* 已发送起始条件,与0x18相同处理 */ 243. // break;244. case 0x10: /* 已发送重复起始条件 */ 245. I2DAT = I2cAddr; /* 发送地址 */ 246. I2CONCLR = 0x28; /* 清除标志 */ 247. break;248. case 0x18: /* 已发送SLA+W,并已接收应答 */ 249. I2DAT =*I2cBuf++;250. I2cNbyte--;251. I2CONCLR = 0x28; /* 清除标志 */ 252. break;253. case 0x28: /* 已发送I2C数据,并接收到应答 */ 254. if (I2cNbyte > 0)255. {256. I2DAT = *I2cBuf++;257. I2cNbyte--;258. I2CONCLR = 0x28; /* 清除标志 */ 259. }260. else261. {262. OSMboxPost(I2cMbox, (void *)I2C_WRITE_END); 263. VICIntEnClr =1 << 9; /* 禁止能I2c中断 */ 264. }265. break;266. case 0x20: /* 已发送SLA+W;已接收非ACK, 与0x48处理相同 */ 267. // break;268. case 0x30: /* 已发送I2DAT中的数据字节;已接收非ACK, 与0x48处理相同 */269. // break;270. case 0x48: /* 已发送SLA+R;已接收非ACK */271. I2CONSET = 1 << 4; /* 发送停止信号 */ 272. OSMboxPost(I2cMbox, (void *)I2C_ACK_ERR); 273. I2CONCLR = 0x28; /* 清除标志 */ 274. break;275. case 0x38: /* 在SLA+R/W或数据字节中丢失仲裁 */ 276. OSMboxPost(I2cMbox, (void *)I2C_NOT_GET_BUS); 277. I2CONCLR = 0x28; /* 清除标志 */ 278. break;279. case 0x40: /* 已发送SLA+R;已接收ACK */ 280. if (I2cNbyte <= 1) 281. {282. I2CONCLR = 1 << 2; /* 下次发送非应答信号 */ 283. }284. else285. {286. I2CONSET= 1 << 2; /* 下次发送应答信号 */ 287. }288. I2CONCLR = 0x28; /* 清除标志 */ 289. break;290. case 0x50: /* 已接收数据字节;已发送ACK */ 291. *I2cBuf++ =I2DAT; /* 接收数据 */ 292. I2cNbyte--;293. if (I2cNbyte <= 1)294. {295. I2CONCLR = 1 << 2; /* 下次发送非应答信号 */ 296. }297. I2CONCLR = 0x28; /* 清除标志 */ 298. break;299. case 0x58: /* 已接收数据字节;已返发送ACK */ 300. *I2cBuf =I2DAT; /* 接收数据 */ 301. I2cNbyte--;302. I2CONSET= 1 << 4; /* 结束总线 */ 303. OSMboxPost(I2cMbox, (void *)I2C_READ_END); 304. I2CONCLR = 0x28; /* 清除标志 */ 305. break;306. default:307. I2CONCLR = 0x28; /* 清除标志 */ 308. break;309. }310.311. VICVectAddr = 0; /* 通知中断控制器中断结束 */ 312.OS_EXIT_CRITICAL();313. }314./*********************************************************************** **********************************315. ** End Of File316.************************************************************************ ********************************/。

I2C总线8位远程IO扩展口芯片PCF8574的驱动程序

I2C总线8位远程IO扩展口芯片PCF8574的驱动程序

//...‎.....‎.....‎.....‎.....‎.....‎.....‎.....‎//名称‎: PCF‎8574(‎A).c ‎I2C扩展‎8位I/O‎芯片的接口‎程序//‎编程: 不‎详//日‎期: 20‎11102‎5//‎//发现‎问题请指点‎,谢谢!‎//...‎.....‎.....‎.....‎.....‎.....‎.....‎.....‎//CP‎U: 89‎C55 1‎1.059‎2MHz‎//环境:‎Keil‎C51 ‎V8.01‎//引脚‎定义:/‎/CPU‎_P2.0‎--- ‎P CF85‎74X_S‎C L 时钟‎// C‎P U_P2‎.1 --‎-PCF‎8574X‎_SDA ‎数据//‎CPU_‎P2.2 ‎--- P‎C F857‎4X_IN‎T中断‎//...‎.....‎.....‎.....‎.....‎.....‎.....‎.....‎#inc‎l ude ‎<Publ‎i c.h>‎#inc‎l ude ‎<Intr‎i ns.h‎>#in‎c lude‎"del‎a y_s.‎h"#i‎n clud‎e "pc‎f8574‎.h"‎//PC‎F8574‎(A)芯片‎指令的定义‎#def‎i ne P‎C F857‎4_WRI‎T E 0x‎40 /‎/器件地址‎= 011‎1 A2 ‎A1 A0‎r/w‎#defi‎n e PC‎F8574‎_READ‎0x41‎//器‎件地址= ‎0111 ‎A2 A1‎A0 r‎/w#d‎e fine‎PCF8‎574A_‎W RITE‎0x70‎//器‎件地址= ‎0111 ‎A2 A1‎A0 r‎/w#d‎e fine‎PCF8‎574A_‎R EAD ‎0x71 ‎//器件‎地址= 0‎111 A‎2 A1 ‎A0 r/‎w#d‎e fine‎P CF8‎574X_‎R EGIS‎T ER_A‎D DR_M‎A X 7 ‎//器件内‎部寄存器地‎址的最大值‎//‎内部函数‎s tati‎c voi‎d i2‎c_sta‎r t_co‎n d(vo‎i d);‎s tati‎c voi‎d i2‎c_sto‎p_con‎d(voi‎d);s‎t atic‎ucha‎r i2c‎_read‎_byte‎(void‎);st‎a tic ‎u char‎i2c_‎r ead_‎b yte_‎n ack(‎v oid)‎;sta‎t ic v‎o id ‎i2c_w‎r ite_‎b yte(‎u char‎da);‎//=‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎= ====‎=====‎=====‎=//接‎口调用函数‎部分//‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎//序号‎:// ‎HD_P‎C F857‎4X_S0‎1//功‎能:/‎/读出‎芯片的复位‎状态‎// i‎s_pcf‎8574a‎=1 是‎A芯片‎// a‎d d_of‎_part‎器件的子‎地址 0~‎3//输‎出:/‎/端口‎的数据/‎/****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎**uc‎h ar P‎C F857‎4X_re‎a d_io‎(ucha‎r is_‎p cf85‎74a, ‎u char‎add_‎o f_pa‎r t){‎ucha‎r i;‎i2c_‎s tart‎_cond‎();‎i f(is‎_pcf8‎574a ‎!=0)‎{‎i2c_w‎r ite_‎b yte(‎P CF85‎74A_R‎E AD |‎((add‎_of_p‎a rt <‎<1) &‎0x0E)‎);//器‎件地址=0‎111 A‎2 A1 ‎A0 r/‎w}‎else‎{‎i2c‎_writ‎e_byt‎e(PCF‎8574_‎R EAD ‎|((ad‎d_of_‎p art ‎<<1) ‎&0x0E‎));//‎器件地址=‎0100 ‎A2 A1‎A0 r‎/w}‎i =‎i2c_r‎e ad_b‎y te_n‎a ck()‎;/‎/顺序读的‎方式读出一‎个字节‎i2c_s‎t op_c‎o nd()‎;re‎t urn(‎i);}‎//*‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎****‎//序号:‎// ‎H D_PC‎F8574‎X_S02‎//功能‎://‎写数据‎到I/O端‎口//输‎入:/‎/is‎_pcf8‎574a ‎=1 是A‎芯片/‎/ad‎d_of_‎p art:‎器件的‎子地址 0‎~7//‎dat‎:写入‎的字节/‎/输出: ‎// ‎无//*‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎void‎PCF8‎574X_‎w rite‎_io(u‎c har ‎i s_pc‎f8574‎a, uc‎h ar a‎d d_of‎_part‎, uch‎a r da‎t){‎i2c_‎s tart‎_cond‎();‎i f(is‎_pcf8‎574a ‎!=0)‎{‎i2c_w‎r ite_‎b yte(‎P CF85‎74A_W‎R ITE ‎|((ad‎d_of_‎p art ‎<<1) ‎&0x0E‎)); /‎/器件地址‎=0111‎A2 A‎1 A0 ‎r/we‎l se‎{i‎2c_wr‎i te_b‎y te(P‎C F857‎4_WRI‎T E |(‎(add_‎o f_pa‎r t <<‎1) &0‎x0E))‎;//器‎件地址=0‎100 A‎2 A1 ‎A0 r/‎w}‎i2c‎_writ‎e_byt‎e(dat‎);‎i2c_s‎t op_c‎o nd()‎;}‎//===‎=====‎=====‎=//内‎部调用函数‎部分//‎=====‎=====‎====‎//--‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎----‎//I2C‎发启始条‎件:时钟线‎为高时数据‎线发生下降‎沿跳变/‎/----‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎--st‎a tic ‎v oid ‎i2c_s‎t art_‎c ond(‎v oid)‎{C‎O DE_S‎C L_LO‎W;_‎D ELAY‎_NOP3‎;CO‎D E_SD‎A_HIG‎H;_‎D ELAY‎_NOP3‎;CO‎D E_SC‎L_HIG‎H;_‎D ELAY‎_NOP3‎;CO‎D E_SD‎A_LOW‎;_D‎E LAY_‎N OP3;‎}/‎/----‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎-//I‎2C 发结‎束条件:时‎钟线为高时‎数据线发生‎上升沿跳变‎//--‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎---s‎t atic‎void‎i2c_‎s top_‎c ond(‎v oid)‎{C‎O DE_S‎C L_LO‎W;_‎D ELAY‎_NOP3‎;CO‎D E_SD‎A_LOW‎;_D‎E LAY_‎N OP3;‎COD‎E_SCL‎_HIGH‎;_D‎E LAY_‎N OP3;‎COD‎E_SDA‎_HIGH‎;_D‎E LAY_‎N OP3;‎}/‎/----‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎-// ‎I2C 读‎取一个中间‎字节的数据‎//--‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎---/‎*sta‎t ic u‎c har ‎i2c_r‎e ad_b‎y te(v‎o id)‎{uc‎h ar i‎;uc‎h ar d‎a=0;‎for(‎i =0;‎i<8;‎i++)‎{‎da <‎<=1; ‎//传输‎的数据高位‎在前‎C ODE_‎S CL_L‎O W;‎_DEL‎A Y_NO‎P3;‎CODE‎_SCL_‎H IGH;‎//时‎钟为高时读‎数据‎//‎N OP3;‎if‎(JUD‎G E_PC‎F8574‎X_SDA‎) da+‎+;}‎COD‎E_SCL‎_LOW;‎_DE‎L AY_N‎O P3;‎CODE‎_SDA_‎L OW; ‎//发‎送应答位‎_DEL‎A Y_NO‎P3;‎C ODE_‎S CL_H‎I GH;‎_DEL‎A Y_NO‎P3;‎C ODE_‎S CL_L‎O W;‎_DELA‎Y_NOP‎3;C‎O DE_S‎D A_HI‎G H;‎r etur‎n(da)‎;}*‎///-‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎----‎// I2‎C读取一‎个结尾字节‎的数据/‎/----‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎-sta‎t ic u‎c har ‎i2c_r‎e ad_b‎y te_n‎a ck(v‎o id)‎{uc‎h ar i‎;uc‎h ar d‎a =0;‎for‎(i =‎0; i<‎8; i+‎+){‎da‎<<=1‎;C‎O DE_S‎C L_LO‎W;‎_DELA‎Y_NOP‎3;‎C ODE_‎S CL_H‎I GH;‎‎//NOP‎3;‎i f(JU‎D GE_P‎C F857‎4X_SD‎A) da‎++;‎}CO‎D E_SC‎L_LOW‎;_D‎E LAY_‎N OP3;‎COD‎E_SDA‎_HIGH‎;_D‎E LAY_‎N OP3;‎COD‎E_SCL‎_HIGH‎;_D‎E LAY_‎N OP3;‎COD‎E_SCL‎_LOW;‎ret‎u rn( ‎d a );‎}/‎/----‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎-// ‎I2C 写‎入一个字节‎的数据/‎/----‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎-sta‎t ic v‎o id i‎2c_wr‎i te_b‎y te(u‎c har ‎d a )‎{uc‎h ar i‎;fo‎r(i =‎0; i<‎8; i+‎+){‎CO‎D E_SC‎L_LOW‎;i‎f(da&‎0x80)‎{‎CO‎D E_SD‎A_HIG‎H;‎}e‎l se‎{‎CODE‎_SDA_‎L OW;‎}‎CODE‎_SCL_‎H IGH;‎da‎<<=1‎;}‎CODE‎_SCL_‎L OW; ‎//第8‎个SCL下‎降沿,写入‎8位数据‎_DEL‎A Y_NO‎P3;‎C ODE_‎S DA_H‎I GH;‎_DEL‎A Y_NO‎P3;‎C ODE_‎S CL_H‎I GH;‎}//‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎== ===‎=====‎=====‎==/‎/End ‎O f Fi‎l e‎‎。

stm32的ADS1110驱动程序(模拟I2C)

stm32的ADS1110驱动程序(模拟I2C)

enum ENUM_TWI_REPLY { TWI_NACK=0 ,TWI_ACK=1 }; enum ENUM_TWI_BUS_STATE { TWI_READY=0 ,TWI_BUS_BUSY=1 ,TWI_BUS_ERROR=2 }; #define TWI_RETRY_COUNT 3 //重试次数 void u8 void u8 u8 u8 void void void u16 u16 TWI_Initialize(void); TWI_START(void); TWI_STOP(void); TWI_SendByte(u8 Data); TWI_ReceiveByte(void); TWI_WaitAck(void); TWI_SendACK(void); TWI_SendNACK(void); ads1110Config(void); RD_ADS(void); get_ad_result(void);
-4-
F:\单片机\ARM\程序\ADS1110.c
2013年1月8日 21:19
TWI_SDA_1; TWI_NOP; TWI_SCL_0; TWI_NOP; //////DebugPrint("TWI_SendNACK\n"); } u8 TWI_WaitAck(void) { TWI_SCL_0; TWI_NOP; TWI_SDA_1; TWI_NOP; TWI_SCL_1; TWI_NOP; if(TWI_SDA_STATE) { TWI_SCL_0; return 0x00; } TWI_SCL_0; return 0x01; } /******************************************************************************* * 函数名称: TWI_SendByte * 描 述: 发送一个字节 * * 输 入: 要发送的数据(1字节) * 输 出: 无 * 返 回: TWI_ACK/TWI_NACK * 作 者: * 修改日期: 2012年10月20日 *******************************************************************************/ u8 TWI_SendByte(u8 Data) { u8 i; TWI_SCL_0; for(i=0;i<8;i++) { TWI_SCL_0; TWI_NOP; //---------数据建立---------if(Data&0x80) { TWI_SDA_1; } else {

I2C_24C64驱动程序

I2C_24C64驱动程序
else {
if(I2C_dat_t < I2C_SOP_NUM) {
I2C->DATA = *I2C_ptr ++; /* ??? */
I2C->CON.STA = 0; /* I2C */
I2C->CON.STO = 1; /* I2C */
I2C_end = 1;
}
I2C_dat_t ++;
}
}
}
else if(Device_addr == 0xa6)
{
I2C->CON.STO = 0; /* I2C */
}
else {
I2C->DATA = *I2C_ptr ++; /* ??? */
I2C->CON.STA = 0; /* I2C */
}
break;
case 0x58: /*receive a data and back a ACK bit */
*I2C_ptr = I2C->DATA ;
I2C->CON.STA = 0; /* I2C */
I2C->CON.STO = 1; /* I2C */
I2C->CON.STO = 0; /* I2C */
break;
case 0x18: /*?????????? ACK ? */
case 0x28: /*?????????? ACK ? */
I2C_f_t ++;
if(Device_addr == 0xa0)
SYS->IPRSTC2.I2C_RST = 0; /* I2C ?? ???? */
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

i2c芯片的驱动程序(汇编)本文对AT24系列存贮器和AT89系列单片机的特征及总线状态作为介绍,并以AT24C01与AT89C2051为例详细描述了通用存贮器IC卡的工作原理及用单片机对其进行读写操作的基本电路连接和软件编程方法。

通用存贮器IC卡是由通用存贮器芯片封装而成的,由于它的结构和功能简单,生产成本低,使用方便,因此在各领域都得到了广泛的应用。

目前用于IC卡的通用存贮器芯片多为E2PROM,其常用的协议主要有两线串行连接协议(I2C)和三线串行链接协议,其中比较常用的是ATMEL公司生产的AT24系列芯片。

以该系列中的AT24C01为例,它具有1k的存贮容量,适用于2V~5V的低电压/标准电压的操作,具有低功耗和高可靠性等优点。

而AT89C2051虽是ATMEL公司89系列单片机的低档型,但它具有2k的FLASHROM(可重编闪速存贮器)、128×8位内部RAM及全静态操作方式,同样也具有低功耗和较强的功能。

下面以AT24C2051为例,对通用存贮器IC卡的工作原理及基本电路连线作一介绍,该线路简单,使用灵活,能可靠地对通用存贮器IC卡进行读写。

2 硬件特性2.1 AT24系列存贮器的特性AT24系列存贮器芯片采用CMOS工艺制造,内置有高压泵,可在单电压供电条件下工作。

其标准封装为8脚DIP封装形式,各引脚的功能说明如下:SCL:串行时钟。

在该脚的上升沿时,系统将数据输入到每个EEPROM器件,在下降沿时输出。

SDA:串行数据。

该引脚为开漏极驱动,可双向传送数据。

A0、A1、A2:器件/页面寻址。

为器件地址输入端。

在AT24C01/02中,该引脚被硬连接。

Vcc:一般输入+5V的工作电压。

图1是符合ISO7816-2标准的IC卡的触点图。

对于AT24系列通用存贮器IC卡来说,通常只需使用四个触点。

AT24C01的内部组态为128个8位字节,而对随机字寻址则需要一个7位地址。

2.2 总线状态及时序A24C01的SCL及SDA两总线可通过一个电阻上拉为高电平,SDA上的数据仅在SCL为低电平时周期才能改变。

当SCL为高电平时,SDA的改变表示“开始”和“停止”状态。

此时,所有地址和数据字都以8位串行码方式输入输出EEPROM。

开始状态:SCL为高电平时,SDA由高电平转入低电平。

该命令必须在其它命令前执行。

停止状态:SCL为高电平时,SDA由低电平转入高电平。

该命令可终止所有通讯。

确认:相同总线上的设备在收到数据后,以置SDA为低电平的方式对其进行确认。

2.3 器件寻址AT24系列EEPROM在开始状态后需紧接一个8位器件地址,以进行应读写操作。

设备寻址码的高4位为1、0、1、0,对于AT24C01/02,寻址码高4位后面的三位是器件寻址码,与它们的硬连线管脚相对应。

最低应是读写选择位,置0时可激发读操作。

具体的格式如下:1010A2A1A0R/W2.4 AT89C2051芯片AT89C2051是MCS-51产品的兼容型,它具有2k的FLASHROM、128字节ROM,15根I/O引线、两个16位定时/计数器、一个五向量两级中断结构、一个全双工串行口、一个精密模拟比较器以及片内振荡电路和时钟电路。

它的P1口和P3口是双向I/O口,其中P1.2~P1.7、P3.0~P3.5和P3.7带有内部上拉电阻。

在AT89C2051用作输入端时,将首先向引脚写“1”而使内部M OS管截止以便引脚处于悬浮状态,从而可获得高阻抗输入。

图2为通用存贮器IC卡的基本电路连接图。

3 读写操作软件当系统采用6MHz晶体振荡器时所定义的I/O口线及器件地址如下:SCL BIT P1.7SDA BIT P1.6DEVICEAD_W DATA 10100000B ;写卡器件地址DEVICEAD_R DATA 10100001B ;读卡器件地址3.1 开始条件(START_IC)在开始条件下,当SCL为高电平时,SDA由高转为低。

程序如下:START_IC:CLR SCL;SCL低电平时才允许SDA更改NOP ;加入空指令延时以确保信号可靠NOPSETB SDANOPNOPSETB SCLNOPNOPCLR SDANOPNOPCLR SCLNOPRET3.2 停止条件(STOP_C)在停止条件下,当SCL为高电平时,SDA由低转为高。

程序如下:STOP_IC:CLR SCLNOPNOPCLR SDANOPNOPSETB SCLNOPNOPSETB SDANOPNOPCLR SCLNOPNOPCLR SDARET3.3 确认信号(ACK_IC)在接收方应答下,每收到一字节后便将SDA电平拉低,程序如下:ACK_IC:CLR SCLNOPNOPCLR SDANOPNOPSEIB SCLNOPNOPCLR SCLNOPSETB SDANOPRET3.4 写一字节数据到IC卡(WR_BYTE)在下列程序中,参数A表示源数据,R5表示字节位数。

WR_BYTE:MOV R5,#08 ;一字节8位数据CLR SCLNOPNOPWR_BYTE1:RLC A ;带进位位左移,A.8->CMOV SDA,C ;SCL低电平时改变SDA上的数据NOPSETB SCL ;拉高SCL把数据发送出去NOPNOPCLR SCLNOPNOPDJNZ R5,WR_BYTE1;依次发送A中的8位数据SETB SDASETB SCLJB SDA,$ ;等待IC卡确认信号CLR SCLNOPRET此子程序的主要作用是按照定义的时序,顺序左移A中一字节8位数据,并通过引脚传送出去。

当一字节发完后,等待IC卡发回的确认信号。

3.5 从IC卡读一字节(RD+BYTE)从IC卡中读一字节的源程序如下:RD_BYTE:MOV R5,#08SETB SDA ;设备SDA为读状态CLR A ;清空A寄存器RD_BTYE1:MOV C,SDA ;读一位数据到进位位RLC A ;左移数据到A.0SETB SCLNOPNOPCLR SCLNOPNOPDJNZ R5,RD_BYTE1;依次读出8位数据到A中RET ;无应答信号利用该程序可将读出的数据存放在A中。

需要注意的是:读数据的器件不是通过确认状态来应答的,而是随后产生一个停止状态。

3.6 字节写入模式写数据(WRITE_BYTE)下列程序中的参数为:R6= =目的地址,A= =数据;数据如下:WRITE_BYTE:PUSH ACC ;保存A中的数据LCALL START_IC ;发开始信号MOV A,#DEVICEAD_W;写入器件地址LCAL WR_BYTEMOV A,R6 ;写入字节地址LCALL WR_BYTEPOP ACC ;恢复A中数据LCALL WR_BYTE ;写入数据LCALL STOP_ICRET在收到8位数据后,EEPROM将通过SDA来回送确认信号,而传送设备必须用停止状态来终止写操作。

这时,EEPROM将进入一个内时固定存贮器的写入周期并且禁止在此其间的所有输入,直到写操作完成后才对通讯应答。

其写入周期可自定义,最大为10ms。

3.7 页面写入模式写数据(WRITE_PAGE)以下程序中的参数为P0= =源指针,R6= =目的地址,R7= =页面长度。

WRITE_PAGE:LCALL START_ICMOV A,#DEVICEAD_WLCALL WR_BYTEMOV A,R6LCALL WR_BYTEWRITE_PAGE1:MOV A,@R0LCALL WR_BYTEINC R0DJNZ R7,WRITE_PAGE1LCALL STOP_ICRETAT24C01/02可利用上述程序进行8字节的页面写入,它的操作类似于写字节。

不同的是,它无需在第一个字节送出后才以停止状态,不同在收到确认信号后,再传送7个字节的数据码,最后以停止状态来终止页面写序列。

AT24C04/08/16的页面为16字节。

3.8 立即地址读模式(READ_BYTEC)立即地址读模式读一字节数据的程序如下:READ_BYTEC:LCALL START_ICMOV A,#DEVICEAD_RLCALL WR_BYTELCALL RD_BYTE ;读出默认地址数据LCALL STOP_IC ;发停止状态应答RET该程序执行后,其内部数据字地址指针将保持在上次读写操作访问的最后一个地址,并按1递增且在芯片上电期间一直有效。

只有当地址为页面的最末时,下次访问才滚动到该页面的首地址。

3.9 随机地址读模式(READ_BYTER)在下列程序中,R6= =源地址,程序如下:READ_BYTER:LCALL START_ICMOV A,#DEVICEAD_W ;执行空字节写序列LCALL WR_BYTE ;载入数据地址MOV A,R6LCALL WR_BYTELCALL START_ICMOV A,#DEVICEAD_R ;立即地址读取LCALL WR_BYTELCALL DR_BYTELCALL STOP_ICRET读操作模式需要一个字节写序列载入数据地址。

在器件和数据地址写入并得到确认后,将再产生另一个开始条件,并送出读操作器件的地址,同时激发一个立即地址读取。

3.10 顺序地址读取(READ_BYTES)在下列程序中:R0= =目的指针;R7= =数据长度,程序如下:READ+BYTES:LCALL START_ICMOV A,#DEVICEAD_RLCALL WR_BYTEREAD_BYTES2:LCALL RD_BYTEMOV @R0,A ;存放数据到目的地址INC R0DJNZ R7,READ_BYTES1LCALL STOP_IC ;读写指定长度后停止RETREAD_BYTES1:LCALL ACK_IC ;收到数据后发确认信号SJMP READ_BYTES2其中顺序读取由立即寻址读或随机地址读激发,并在收到一字节数据后发确认信号应答。

当读数器件以停止状态应答时,操作被终止。

4 总结该系统结构简单,在实际运行时具有很高的可靠性,同时具有一定的可扩展性,并可通过单片机的串行口经电平转换后直接与计算机相连,以进行数据通讯。

另外,也可根据需要连接到其它引脚或卡座触点,如果适当改进电路和程序,还可读写加密卡和CPU卡等。

相关文档
最新文档