📄 i2c.s
字号:
.module i2c.c
.area text(rom, con, rel)
.dbfile E:\MYWORK~1\开发设计\AVR-MP3\mp3开发板光盘\驱动程序\MP3BOA~1.8\i2c.c
.dbfunc e I2C_Ini _I2C_Ini fV
.even
_I2C_Ini::
.dbline -1
.dbline 15
; //ICC-AVR application builder : 2005-11-12 17:11:59
; // Target : M16
; // Crystal: 8.0000Mhz
; // copyright:鲁军波(endylu)
; // www.shop34612283.taobao.com
; // www.adembed.com
; #include <iom16v.h>
; #include <macros.h>
; #include "main.h"
;
;
; //=======================================================================
; //初始化端口
; void I2C_Ini(void)
; {
.dbline 16
; i2c_ddr|=(1<<SCL); //SCK为输出
sbi 0x14,0
.dbline 17
; i2c_ddr|=(1<<SDA); //SDA为双向的,先设置为输出
sbi 0x14,1
.dbline -2
L1:
.dbline 0 ; func end
ret
.dbend
.dbfunc e IICStart _IICStart fV
.even
_IICStart::
.dbline -1
.dbline 24
;
;
; }
; //=======================================================================
; //启动总线。根据IIC协议,SCL为1时,SDA从1转变为0。
; void IICStart(void)
; { SCL_0;
.dbline 24
.dbline 24
cbi 0x15,0
.dbline 24
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 24
.dbline 24
.dbline 25
; SDA_1;
.dbline 25
sbi 0x15,1
.dbline 25
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 25
.dbline 25
.dbline 26
; SCL_1;
.dbline 26
sbi 0x15,0
.dbline 26
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 26
.dbline 26
.dbline 27
; SDA_0;
.dbline 27
cbi 0x15,1
.dbline 27
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 27
.dbline 27
.dbline 28
; SCL_0;
.dbline 28
cbi 0x15,0
.dbline 28
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 28
.dbline 28
.dbline -2
L2:
.dbline 0 ; func end
ret
.dbend
.dbfunc e IICStop _IICStop fV
.even
_IICStop::
.dbline -1
.dbline 33
; }
; //=======================================================================
; //停止IIC总线。根据IIC协议,SCL为1时,SDA从0转变为1。
; void IICStop(void)
; {
.dbline 34
; SCL_0;
.dbline 34
cbi 0x15,0
.dbline 34
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 34
.dbline 34
.dbline 35
; SDA_0;
.dbline 35
cbi 0x15,1
.dbline 35
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 35
.dbline 35
.dbline 36
; SCL_1;
.dbline 36
sbi 0x15,0
.dbline 36
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 36
.dbline 36
.dbline 37
; SDA_1;
.dbline 37
sbi 0x15,1
.dbline 37
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 37
.dbline 37
.dbline -2
L3:
.dbline 0 ; func end
ret
.dbend
.dbfunc e IICRecAck _IICRecAck fc
; ack -> R20
.even
_IICRecAck::
xcall push_gset1
.dbline -1
.dbline 45
; //SCL_0;
; }
; //=======================================================================
; //检查应答位,向I2C写数据时,I2C设备(EEPROM)正常接受到数据后在第9周期发出0应答,
; //如果不正常接受到数据,则不以0应答而进入待命状态。
; //写数据后需检查I2C设备是否有0应答。
; unsigned char IICRecAck(void)
; {
.dbline 48
; uint8 ack;
;
; SCL_0;
.dbline 48
cbi 0x15,0
.dbline 48
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 48
.dbline 48
.dbline 49
; SDA_0;
.dbline 49
cbi 0x15,1
.dbline 49
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 49
.dbline 49
.dbline 50
; SCL_1;
.dbline 50
sbi 0x15,0
.dbline 50
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 50
.dbline 50
.dbline 52
;
; i2c_ddr&=~(1<<SDA); //设置SDA为输入
cbi 0x14,1
.dbline 53
; i2c_port|=1<<SDA; //上拉
sbi 0x15,1
.dbline 54
; ack=(i2c_pin & (1<<SDA)); //读SDA应答位
in R20,0x13
andi R20,2
.dbline 55
; i2c_ddr|=(1<<SDA); //恢复为输出
sbi 0x14,1
.dbline 57
;
; SCL_0;
.dbline 57
cbi 0x15,0
.dbline 57
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 57
.dbline 57
.dbline 58
; return(ack);
mov R16,R20
.dbline -2
L4:
xcall pop_gset1
.dbline 0 ; func end
ret
.dbsym r ack 20 c
.dbend
.dbfunc e IICReceiveByte _IICReceiveByte fc
; i -> R20
; receivebyte -> R22
.even
_IICReceiveByte::
xcall push_gset2
.dbline -1
.dbline 63
; }
; //=======================================================================
; //从IIC总线上读数据。
; unsigned char IICReceiveByte(void)
; {
.dbline 64
; uint8 receivebyte=0,i=8;
clr R22
.dbline 64
ldi R20,8
.dbline 66
;
; i2c_ddr&=~(1<<SDA); //设置SDA为输入
cbi 0x14,1
.dbline 67
; i2c_port|=1<<SDA; //上拉
sbi 0x15,1
.dbline 68
; i2c_port&=~(1<<SCL);
cbi 0x15,0
xjmp L7
L6:
.dbline 71
;
; while(i--)
; {
.dbline 72
; SCL_1;
.dbline 72
sbi 0x15,0
.dbline 72
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 72
.dbline 72
.dbline 73
; receivebyte <<= 1;
lsl R22
.dbline 74
; if(i2c_pin & (1<<SDA)) receivebyte |= 1;
sbis 0x13,1
rjmp L9
.dbline 74
ori R22,1
L9:
.dbline 75
.dbline 75
cbi 0x15,0
.dbline 75
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 75
.dbline 75
.dbline 76
L7:
.dbline 70
mov R2,R20
clr R3
subi R20,1
tst R2
brne L6
.dbline 78
; SCL_0;
; }
;
; i2c_ddr|=(1<<SDA); //恢复SDA为输出
sbi 0x14,1
.dbline 79
; return(receivebyte);
mov R16,R22
.dbline -2
L5:
xcall pop_gset2
.dbline 0 ; func end
ret
.dbsym r i 20 c
.dbsym r receivebyte 22 c
.dbend
.dbfunc e IICACK _IICACK fV
.even
_IICACK::
.dbline -1
.dbline 86
; }
;
;
; //=======================================================================
; //对IIC总线产生应答。读I2C设备时,如果下一步还要读则产生0应答。
; void IICACK(void)
; {
.dbline 87
; SDA_0;
.dbline 87
cbi 0x15,1
.dbline 87
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 87
.dbline 87
.dbline 88
; SCL_1;
.dbline 88
sbi 0x15,0
.dbline 88
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 88
.dbline 88
.dbline 89
; SCL_0;
.dbline 89
cbi 0x15,0
.dbline 89
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 89
.dbline 89
.dbline 90
; SDA_1;
.dbline 90
sbi 0x15,1
.dbline 90
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 90
.dbline 90
.dbline -2
L11:
.dbline 0 ; func end
ret
.dbend
.dbfunc e IICNoAck _IICNoAck fV
.even
_IICNoAck::
.dbline -1
.dbline 95
; }
; //=======================================================================
; //不对IIC总线产生应答。读I2C设备时,如果下一步不需要读则产生1应答(即不应答)。
; void IICNoAck(void)
; {
.dbline 96
; SDA_1;
.dbline 96
sbi 0x15,1
.dbline 96
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 96
.dbline 96
.dbline 97
; SCL_1;
.dbline 97
sbi 0x15,0
.dbline 97
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 97
.dbline 97
.dbline 98
; SCL_0;
.dbline 98
cbi 0x15,0
.dbline 98
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 98
.dbline 98
.dbline -2
L12:
.dbline 0 ; func end
ret
.dbend
.dbfunc e IICSendByte _IICSendByte fV
; j -> R20
; sendbyte -> R22
.even
_IICSendByte::
xcall push_gset2
mov R22,R16
.dbline -1
.dbline 103
; }
; //=======================================================================
; //向IIC总线写数据。SCL=0时SDA的数据可改变,SCL=1时需保持SDA数据稳定。
; void IICSendByte(unsigned char sendbyte)
; {
.dbline 104
; uint8 j=8;
ldi R20,8
.dbline 105
; for(;j>0;j--)
xjmp L17
L14:
.dbline 106
; {
.dbline 107
; SCL_0;
.dbline 107
cbi 0x15,0
.dbline 107
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 107
.dbline 107
.dbline 109
;
; if(sendbyte&0x80) SDA_1 //SCL=0时写数据到SDA
sbrs R22,7
rjmp L18
.dbline 109
.dbline 109
sbi 0x15,1
.dbline 109
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 109
xjmp L19
L18:
.dbline 110
; else SDA_0
.dbline 110
cbi 0x15,1
.dbline 110
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 110
L19:
.dbline 112
lsl R22
.dbline 114
.dbline 114
sbi 0x15,0
.dbline 114
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 114
.dbline 114
.dbline 115
L15:
.dbline 105
dec R20
L17:
.dbline 105
clr R2
cp R2,R20
brlo L14
.dbline 116
;
; sendbyte<<=1;
;
; SCL_1;
; }
; SCL_0;
.dbline 116
cbi 0x15,0
.dbline 116
ldi R16,2
ldi R17,0
xcall _Delay_us
.dbline 116
.dbline 116
.dbline -2
L13:
xcall pop_gset2
.dbline 0 ; func end
ret
.dbsym r j 20 c
.dbsym r sendbyte 22 c
.dbend
.dbfunc e sta_ReadDevice _sta_ReadDevice fc
; ErrorCount -> R22
; data -> R20
; device -> R10
; subAddr -> R12
.even
_sta_ReadDevice::
xcall push_gset4
mov R10,R18
mov R12,R16
.dbline -1
.dbline 122
; }
;
; //=======================================================================
; //通过I2C读STA013
; unsigned char sta_ReadDevice(unsigned char subAddr,uint8 device)
; {
.dbline 123
; uint8 data,ErrorCount=10;
ldi R22,10
xjmp L22
L21:
.dbline 127
; //Delay_us(1200);
;
; while(ErrorCount--)
; {
.dbline 128
; IICStart();
xcall _IICStart
.dbline 129
; IICSendByte(device);
mov R16,R10
xcall _IICSendByte
.dbline 131
;
; if(IICRecAck()) continue; //如果为非0应答,重复写
xcall _IICRecAck
tst R16
breq L24
.dbline 131
xjmp L22
L24:
.dbline 133
;
; IICSendByte(subAddr);
mov R16,R12
xcall _IICSendByte
.dbline 134
; if(IICRecAck()) continue; //如果为非0应答,重复写
xcall _IICRecAck
tst R16
breq L26
.dbline 134
xjmp L22
L26:
.dbline 135
; IICStart();
xcall _IICStart
.dbline 136
; IICSendByte(device | 0x01);
mov R16,R10
ori R16,1
xcall _IICSendByte
.dbline 137
; if(IICRecAck()) continue;
xcall _IICRecAck
tst R16
breq L28
.dbline 137
xjmp L22
L28:
.dbline 140
xcall _IICReceiveByte
mov R20,R16
.dbline 141
xcall _IICNoAck
.dbline 142
xjmp L23
L22:
.dbline 126
mov R2,R22
clr R3
subi R22,1
tst R2
brne L21
L23:
.dbline 144
;
;
; data=IICReceiveByte(); //读数据,并发出1应答,表示不再读。
; IICNoAck();
; break;
; }
; IICStop();
xcall _IICStop
.dbline 145
; return data;
mov R16,R20
.dbline -2
L20:
xcall pop_gset4
.dbline 0 ; func end
ret
.dbsym r ErrorCount 22 c
.dbsym r data 20 c
.dbsym r device 10 c
.dbsym r subAddr 12 c
.dbend
.dbfunc e i2c_Write _i2c_Write fV
; ErrorCount -> R20
; data -> R22
; device -> R10
; subAddr -> R12
.even
_i2c_Write::
xcall push_gset4
mov R10,R18
mov R12,R16
ldd R22,y+8
.dbline -1
.dbline 151
; }
;
; //=======================================================================
; //通过I2C向STA013发送数据
; void i2c_Write(unsigned char subAddr,unsigned char device,unsigned char data)
; {
.dbline 152
; uint8 ErrorCount=10;
ldi R20,10
xjmp L32
L31:
.dbline 155
;
; while(ErrorCount--)
; {
.dbline 156
; IICStart();
xcall _IICStart
.dbline 157
; IICSendByte(device);
mov R16,R10
xcall _IICSendByte
.dbline 158
; if(IICRecAck()) continue; //如果为非0应答,重复写
xcall _IICRecAck
tst R16
breq L34
.dbline 158
xjmp L32
L34:
.dbline 159
; IICSendByte(subAddr);
mov R16,R12
xcall _IICSendByte
.dbline 160
; if(IICRecAck()) continue; //如果为非0应答,重复写
xcall _IICRecAck
tst R16
breq L36
.dbline 160
xjmp L32
L36:
.dbline 162
mov R16,R22
xcall _IICSendByte
.dbline 163
xcall _IICACK
.dbline 165
xjmp L33
L32:
.dbline 154
mov R2,R20
clr R3
subi R20,1
tst R2
brne L31
L33:
.dbline 168
;
; IICSendByte(data);
; IICACK();
;
; break;
; }
;
; IICStop();
xcall _IICStop
.dbline -2
L30:
xcall pop_gset4
.dbline 0 ; func end
ret
.dbsym r ErrorCount 20 c
.dbsym r data 22 c
.dbsym r device 10 c
.dbsym r subAddr 12 c
.dbend
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -