Board logo

标题: 应广单片机系列——用I2C接口读写EEPROM [打印本页]

作者: 我是MT    时间: 2014-5-28 18:32     标题: 应广单片机系列——用I2C接口读写EEPROM

本例是用针对标准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
  本例代码是从实际程序中移植而来,已编译,未做最终调试




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0