原创 应广单片机系列——用I2C接口读写EEPROM

2012-12-20 21:03 2823 19 20 分类: 消费电子

本例是用针对标准I2C接口EEPROM存储器24C02进行读写操作,只要对例程做适当修改,就可以用到大部分控制I2C接口设备的场合。

 

//-----------------------------------------
//应广单片机软件I2C接口例程(MASTER模式)
//本例仅供参考,欢迎指正程序中的问题
//2012年12月20日
//
//作者:戴上举
//邮箱:daishangju@163.com
//博客:forum.eet-cn.com/BLOG_daishangju_334.HTM
//电话:13509678051
//Q  Q:1514292225
//-----------------------------------------
.chip p201cs14a
//{{PADAUK_CODE_OPTION
 .Code_Option Bootup  Slow  // 1024 ILRC
 .Code_Option LVD  2.79V  // Maximum performance = 4 MIPS
 .Code_Option Security Enable  // Security 3/4 words Enable
//}}PADAUK_CODE_OPTION


//定义I2C接口
I2C_SDA equ pa.7
I2C_SCL equ pa.6
I2C_SDA_DIR equ pac.7
I2C_SCL_DIR equ pac.6
I2C_LONG_DLY equ 50
I2C_SHORT_DLY equ 20
I2C_SDA_HIGH equ set1 I2C_SDA 
I2C_SDA_LOW equ set0 I2C_SDA
I2C_SCL_HIGH equ set1 I2C_SCL
I2C_SCL_LOW equ set0 I2C_SCL
I2C_SDA_OUTPUT equ set1 I2C_SDA_DIR
I2C_SDA_INPUT equ set0 I2C_SDA_DIR
I2C_SCL_OUTPUT equ set1 I2C_SCL_DIR
I2C_SCL_INPUT equ set0 I2C_SCL_DIR


//定义I2C变量
byte i2c_rw_addr //读写地址
byte i2c_rw_byte //读写数据
byte i2c_rw_cmd //读写的器件地址
byte i2c_rw_temp //读写过程中间变量
byte i2c_rw_cnt //读写过程中间变量

//
byte Xms
byte ms_cnt

//
byte test_addr
byte test_data

.romadr 0x000
 goto main0
 goto main1

.romadr 0x010
isr_entry:
 pushaf
 intrq = 0
 popaf
 reti


//----------------------------
//产生START信号
//----------------------------
i2c_start:
 I2C_SDA_OUTPUT
 I2C_SCL_OUTPUT
 I2C_SDA_HIGH
 delay I2C_LONG_DLY
 I2C_SCL_HIGH
 delay I2C_LONG_DLY
 I2C_SDA_LOW
 delay I2C_LONG_DLY
 I2C_SCL_LOW
 delay I2C_LONG_DLY
 ret

//----------------------------
//产生STOP信号
//----------------------------
i2c_stop:
 I2C_SCL_LOW
 delay I2C_LONG_DLY
 I2C_SDA_LOW
 delay I2C_LONG_DLY
 I2C_SCL_HIGH
 delay I2C_LONG_DLY
 I2C_SDA_HIGH
 delay I2C_LONG_DLY
 //
 I2C_SCL_INPUT
 I2C_SDA_INPUT
 ret


//----------------------------
//检查SALVE ACK信号
//----------------------------
i2c_slave_ack:
 //don't check ACK
 I2C_SDA_INPUT
 delay I2C_SHORT_DLY
 I2C_SCL_HIGH
 delay I2C_SHORT_DLY
 I2C_SCL_LOW
 delay I2C_SHORT_DLY
 I2C_SDA_OUTPUT
 I2C_SDA_LOW
 delay I2C_SHORT_DLY
 ret

//----------------------------
//输出MASTER ACK信号
//----------------------------
i2c_master_ack:
 I2C_SDA_OUTPUT
 I2C_SDA_LOW
 delay I2C_SHORT_DLY
 I2C_SCL_HIGH
 delay I2C_SHORT_DLY
 I2C_SCL_LOW
 delay I2C_SHORT_DLY
 ret

//----------------------------
//输出MASTER NACK信号
//----------------------------
i2c_master_nack:
 I2C_SDA_OUTPUT
 I2C_SDA_HIGH
 delay I2C_SHORT_DLY
 I2C_SCL_HIGH
 delay I2C_SHORT_DLY
 I2C_SCL_LOW
 delay I2C_SHORT_DLY
 ret


//------------------------------
//写一个字节
//Input: i2c_rw_temp
//Used:  i2c_rw_cnt
//------------------------------
i2c_write_8bit:
 i2c_rw_cnt = 8
i2c_write_8bit_loop:
 slc i2c_rw_temp
 swapc I2C_SDA
 delay I2C_SHORT_DLY
 I2C_SCL_HIGH
 delay I2C_SHORT_DLY
 I2C_SCL_LOW
 delay I2C_SHORT_DLY
 dzsn i2c_rw_cnt
 goto i2c_write_8bit_loop
 ret

//------------------------------
//读一个字节
//Used:   i2c_rw_cnt
//Output: i2c_rw_temp
//------------------------------
i2c_read_8bit:
 i2c_rw_temp = 0
 i2c_rw_cnt = 8
 delay I2C_SHORT_DLY
i2c_read_8bit_loop:
 I2C_SCL_HIGH
 delay I2C_SHORT_DLY
 swapc I2C_SDA
 slc i2c_rw_temp
 I2C_SCL_LOW
 delay I2C_SHORT_DLY
 dzsn i2c_rw_cnt
 goto i2c_read_8bit_loop
 ret

//------------------------------
//Input:  i2c_rw_addr
//        i2c_rw_cmd
//Used:   i2c_rw_cnt
//        i2c_rw_temp
//Output: i2c_rw_byte
//------------------------------
i2c_read_byte:
 //start
 call i2c_start

 //write device address(write)
 i2c_rw_temp = i2c_rw_cmd
 call i2c_write_8bit

 //slave ack
 call i2c_slave_ack

 //write register address
 i2c_rw_temp = i2c_rw_addr
 call i2c_write_8bit

 //slave ack
 //don't check ACK
 call i2c_slave_ack

 //start repeat
 call i2c_start

 //write device address(read)
 i2c_rw_temp = i2c_rw_cmd
 i2c_rw_temp.0 = 1
 call i2c_write_8bit

 //slave ack
 //don't check ACK
 I2C_SDA_INPUT
 delay I2C_SHORT_DLY
 I2C_SCL_HIGH
 delay I2C_SHORT_DLY
 I2C_SCL_LOW
 delay I2C_SHORT_DLY //这里为特殊情况I2C_SDA不用转为输出

 //read data
 i2c_rw_temp = 0
 call i2c_read_8bit
 i2c_rw_byte = i2c_rw_temp //store data

 //master nack
 call i2c_master_nack

 //stop
 call i2c_stop

 //retune
 delay I2C_LONG_DLY
 wdreset
 ret

//------------------------------
//Input:  i2c_rw_addr
//        i2c_rw_byte
//        i2c_rw_cmd
//Used:   i2c_rw_cnt
//        i2c_rw_temp
//------------------------------
i2c_write_byte:
 //start
 call i2c_start

 //write device address
 i2c_rw_temp = i2c_rw_cmd
 call i2c_write_8bit

 //slave ack
 //don't check ACK
 call i2c_slave_ack

 //write register address
 i2c_rw_temp = i2c_rw_addr
 call i2c_write_8bit

 //slave ack
 //don't check ACK
 call i2c_slave_ack

 //write data
 i2c_rw_temp = i2c_rw_byte
 call i2c_write_8bit

 //slave ack
 //don't check ACK
 call i2c_slave_ack

 //stop
 call i2c_stop

 //retune
 delay I2C_LONG_DLY
 wdreset
 ret

EEPROM_RW_CMD equ 0xA0
//------------------------------
//函数名: eeprom_read_byte
//Input:  i2c_rw_addr
//Used:   i2c_rw_cnt
//        i2c_rw_temp
//Output: i2c_rw_byte
//------------------------------
eeprom_read_byte:
 i2c_rw_cmd = EEPROM_RW_CMD
 goto i2c_read_byte //注意这里用的是跳转
//------------------------------
//函数名: eeprom_write_byte
//Input:  i2c_rw_addr
//        i2c_rw_byte
//Used:   i2c_rw_cnt
//        i2c_rw_temp
//注意:  调用完后需要等待一段时间以保证写操作完成
//------------------------------
eeprom_write_byte:
 i2c_rw_cmd = EEPROM_RW_CMD
 goto i2c_write_byte //注意这里用的是跳转

 

//----------------------------------------
//input: ms
//该函数以4M频率为基准时钟实现延时
//----------------------------------------
delayXms:
 while(Xms)
 {
  wdreset
  ms_cnt = 20
  while(ms_cnt)
  {
   delay 195
    ms_cnt--
  }
  Xms--
 }
 ret

 

main0:
 .ADJUST_OTP_IHRCR 8MIPS  // IHRC/2 = 8MIPS, WatchDog Disable, RAM 0,1 temporary be used
 sp = 0x30

 disgint
 inten = 0


 pa = 0b0000_0000
 paph = 0b1101_0000
 pac = 0b0000_0001 
 pb = 0b0000_0000
 pbph = 0b0000_0000
 pbc = 0b1111_1111

 I2C_SDA_INPUT
 I2C_SCL_INPUT

 delay 200

 mov a,0b100_11_111
 mov t16m,a

 clkmd.1 = 1 //enable watch dog
 wdreset


 Xms = 100
 call delayXms

 

 test_data = 0
 test_addr = 0

main0_loop:
 wdreset

 //写E2EPROM
 i2c_rw_addr = test_addr
 i2c_rw_byte = test_data
 call eeprom_write_byte

 //调用EEPROM写操作函数后要等待一段时间,以保证数据写操作完成
 Xms = 20
 call delayXms

 //读E2EPROM
 i2c_rw_addr = test_addr
 call eeprom_read_byte
 if(i2c_rw_byte != test_data)
 {
  //读回的数据比较出错,判断为读写E2PROM出错
  nop
 }

 test_addr ++
 test_data --
 

 goto main0_loop

//----------------FPPA1-------------------
main1: 
 sp = 52
main1_loop:
 goto main1_loop

 

本例代码是从实际程序中移植而来,已编译,未做最终调试

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

liujianyuanf_430418041 2014-1-11 20:58

我住在长江以南,这边用这东西感觉还不错

用户1731580 2014-1-7 15:19

空气能确实不适合北方使用,但是在南方就绰绰有余了,只要保证空气能主机在1℃以上的环境下,就可以合理使用,这一点也不难做到。一般要做到普通民用效果确实不明显,但是如果居住面积比较大,或者用水量比较大,使用空气能的热水器确实能达到同等效果下节省三分之二的能源。 我觉得空气能作为物理能源还十分有潜力,将来也肯定不仅仅能制热。

用户1509947 2013-12-31 10:19

环境温度,用水量、用水温度不同加热时间也不同

用户1406868 2013-12-28 19:52

这个东西夏天能省电电,冬天还不如用电磁炉

用户1377758 2013-12-26 20:02

谢谢提醒,免得上当。

忆轻狂 2013-12-25 21:06

空气能热水器,实际上就是空调,原理相同,结构相同,部件相同,差别就是空调把室内热量压缩到室外,空气能热水器把室外空气热量压缩到室内,加了一个水箱。所以空调能做到的空气能热水器都能做到,空调能满足能量守恒定律,空气能热水器就能,空调能家用,空气能热水器就能,空调能节能,空气能热水器就能。 不是不能做好,而是商家没有去做好,不是空气能热水器不节能,而是它本身原理就决定气温低就不好用。不能因为商家的利益性的商业行为而否定一项技术。

忆轻狂 2013-12-25 20:50

其实这不算是产品院里的问题,因为从原理上就不可避免出现冬天不致暖的问题,但是商家宣传的时候故意回避,或者说隐瞒了这类信息。 我发这个帖子主要是想提醒大家,在商家没讲出来的时候我们应该有基本的原理认识,避免被动上当。

用户1624139 2013-12-25 11:42

使用者的問題??這是產品的使用條件有限制,說白了就是東西不好用,卻說是使用者的問題?比如喜劇裡的無儲能設備的太陽能手電筒一樣,這個產品還有意義嗎?最需要熱水的時候不能出熱水的熱水器,產品明明有重大缺陷,還說是使用者的問題。

自做自受 2013-12-25 11:40

哈!终于看到有人发话啦!
博主您是“一直很推崇空气能热水器”
相反我是“一听说就从心里拒绝空气能热水器”
作为日常民用,可行吗?可谓忽悠老百姓,节能吗?环保吗?
复习一下物质不灭定律和能量守恒定律。
试想一台空气能热水器多少钱?一度电多少钱?消费者等于一次性批量购买了制造者前期增加的耗电(耗能)。更担心的是该产品的MTBF指标是多少?如今使用1年就出故障的消费类电子电器产品常见。

用户1297079 2013-12-25 11:32

我一位好友做的电热水器洗澡后流出去的水是冷水,这样的才是真正的节能的,空气能确实是忽悠
相关推荐阅读
daishangju_162733976 2015-12-19 20:46
个人所见植保无人机
      实在是太久太久没有了上来了,在过去的这段时间里,一些不方便说的原因,还一些方便说的原因,缠绕在一起,让自己封闭(不好意思用蛰伏这个词)一年多,不单是博客没有来,就是邮箱都很少打开。...
daishangju_162733976 2014-10-23 19:48
微观经济1409
位于东莞市凤岗镇的一家小吃店,旁边是一家酒店,老板去年请了7个工人,每天销售5000~7000,今年9月只有1个工人,销售肯定1000以内。   ...
daishangju_162733976 2014-10-23 17:27
市场去哪儿了
好像是从2008年开始,但凡是市场情况不好,总是能见到是经济危机导致欧美市场疲软的解释,看到电视里面安然轰然倒下、华尔街员工茫然抱着纸箱的画面,我对这个解释也是深信不疑。转眼五、六年过去,可是市场...
daishangju_162733976 2014-09-10 14:29
一名电子工程师在深圳的迁移路线图
1999年中,来到宝安区翻身村,在某电子厂工程部当小弟混饭吃,当时小霸王系诸多好汉豪杰正在那边分猪肉。(今天是WWW要搞的前海CBD)   1999年末,转往福田区华强北,在某电子公司开发...
daishangju_162733976 2014-09-05 16:37
另眼看客户“你自己去做,我一定支持你”这句话
我们常常看到或听到这样的事,小X在某行业中打工,经过一番努力,做得还不错,这时候就有客户说:“小X啊,你自己去做吧,我一定支持你”,这个时候小X往往都是已经在考虑是不是要自己出去单干,听到这样的话...
daishangju_162733976 2014-07-03 16:47
谁是优秀的职业经理人?
LEE是公司元老,在公司上下眼里,他能力超凡,数次于水火中力挽狂澜,没有人不承认他是一名福将。LEE有多厉害呢?他主导的产品成功率大约为三分之一,除了他自己,没人知道他是如何选定产品的,甚至他自己...
EE直播间
更多
我要评论
1
19
关闭 站长推荐上一条 /3 下一条