注册 登录
电子技术论坛 返回首页

戴上举的个人空间 https://bbs.elecfans.com/?703024 [收藏] [复制] [分享] [RSS]

博客

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

热度 30已有 6625 次阅读2013-2-28 10:21

  本例是用针对标准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

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

7

路过

雷人
3

握手
5

鲜花

鸡蛋

刚表态过的朋友 (15 人)

返回顶部