1
注:本文是作者以前发表在其个人博客,现在发布到德赢Vwin官网 专栏
本例是用针对标准I2C接口EEPROM存储器24C02进行读写操作,只要对例程做适当修改,就可以用到大部分控制I2C接口设备的场合。
应广单片机软件I2C接口例程(MASTER模式)
本例仅供参考,欢迎指正程序中的问题
//-----------------------------------------
.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
本例代码是从实际程序中移植而来,已编译,未做最终调试
全部0条评论
快来发表一下你的评论吧 !