📄 i2c.s
字号:
.module I2C.c
.area text(rom, con, rel)
.dbfile G:\Mega8程序\TCXO评估板\LedShow\I2C.c
.dbfunc e TWI_init _TWI_init fV
.even
_TWI_init::
.dbline -1
.dbline 79
; /*******************************************************
; 本部分为TWI总线的被控器部分程序,可以完成被控接收、被控发送数据
; 其工作方式与At240×系列的EEPROM的字节读写相同
; 目前问题是EEPROM的读写速度太慢,无法跟上TWI总线速度。
; *///////////////////////////////////////////////////////
;
; #include<iom8v.h>
; #include <macros.h>
; /* AT2402C地址
; 1 0 1 0 A2 A1 A0 R/W
; 前4位为AT240X系列的特征字
; 后3位为可编程位
; 最后一位为读写位
; */
; #define rd_device_add 0xa1 //读地址:0b10100001
; #define wr_device_add 0xa0 //写地址:0b10100000
;
; /*TWI状态定义----MT 主方式传输 MR 主方式接收*/
; #define START 0x08
; #define RE_START 0x10
;
; #define MT_SLA_ACK 0x18
; #define MT_SLA_NOACK 0x20
; #define MT_DATA_ACK 0x28
; #define MT_DATA_NOACK 0x30
;
; #define MR_SLA_ACK 0x40
; #define MR_SLA_NOACK 0x48
; #define MR_DATA_ACK 0x50
; #define MR_DATA_NOACK 0x58
;
; //SR-从机方式接收 ST-从机方式传输 ALL-广播 NOCTRL-主机丢失控制权
; #define SR_SLA_ACK 0x60
; #define SR_SLA_ACK_NOCTRL 0x68
; #define SR_ALL_ACK 0x70
; #define SR_ALL_ACK_NOCTRL 0x78
; #define SR_DATA_ACK 0X80
; #define SR_DATA_NOACK 0X88
; #define SR_ALL_DATA_ACK 0x90
; #define SR_ALL_DATA_NOACK 0x98
; #define SR_STOP_RESTART 0xa0
;
; #define ST_SLA_ACK 0xa8
; #define ST_SLA_ACK_NOCTRL 0xb0
; #define ST_DATA_ACK 0xb8
; #define ST_DATA_NOACK 0xc0
; #define ST_LAST_DATA_ACK 0xc8
;
; ///////////////////////////////////////////////////////////
; #define EE_READ 0xf0
; #define EE_READ_OK 0x50
; #define EE_WRITE 0x0f
; #define EE_WRITE_OK 0x05
; #define EE_WRITE_OVER 0xa5
;
; #define TestAck() (TWSR&0xf8)
; //TWSR--I2C状态寄存器,检查TWI状态,应该将预分频位屏蔽(第三位是保留位)
;
; #define Start() (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE))
; //清除中断标志位,在总线上发出起始信号,激活TWI功能,开放TWI中断
; #define Stop() (TWCR=((1<<TWINT)|(1<<TWSTO)|(1<<TWEN))&(~(1<<TWIE)))
; //清除中断标志位,在总线上发出终止信号,激活TWI功能,关闭TWI中断
; #define MT_NACK (TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE))
; //清除中断标志位,使能TWI功能,开放TWI中断,在主控接收状态下不对SDA线作应答
; #define MT_ACK (TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE)|(1<<TWEA))
; //清除中断标志位,使能TWI功能,开放TWI中断,在主控接收状态下对SDA线作应答
; #define TWItransmit(x) {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE);}
; //写入8位数据到数据寄存器中,同时清除中断标志位,使能TWI功能,开放TWI中断
;
; extern char cDataBuff[];
; extern void rom_write(unsigned int Address,unsigned char Data);
; extern unsigned char rom_read(unsigned int Address);
;
; unsigned char charData;//TWI中断中,传送的数据
; unsigned char charAddr;//TWI中断中,数据所处的EEPROM地址
; unsigned char charState;//TWI中断中,中断所处的状态
;
; void TWI_init(void)
; {
.dbline 80
; DDRC&=0b11001111;//设置PC4、PC5为输入
in R24,0x14
andi R24,207
out 0x14,R24
.dbline 81
; PORTC|=0b00110000;//将SDA、SCL线拉高(内置上拉电阻)
in R24,0x15
ori R24,48
out 0x15,R24
.dbline 82
; charState=EE_READ;
ldi R24,240
sts _charState,R24
.dbline 83
; TWBR=0x00;//波特率寄存器,主机正常情况下应不小于10
clr R2
out 0x0,R2
.dbline 84
; TWSR=0x00;//TWI状态寄存器,时钟分频值1
out 0x1,R2
.dbline 85
; TWAR=0xa0;/*被控器地址寄存器。0xa0为AT2402的地址,可以用ATMEGA8来模拟AT2402。
ldi R24,160
out 0x2,R24
.dbline 87
; 作为从机,应该将被控器的地址写入。注意不要和其他器件相同*/
; TWCR=(TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE)|(1<<TWEA));//清除中断标志位,使能TWI功能,开放TWI中断
ldi R24,197
out 0x36,R24
out 0x36,R24
.dbline -2
L1:
.dbline 0 ; func end
ret
.dbend
.area vector(rom, abs)
.org 34
rjmp _TWI_Ready
.area text(rom, con, rel)
.dbfile G:\Mega8程序\TCXO评估板\LedShow\I2C.c
.area data(ram, con, rel)
.dbfile G:\Mega8程序\TCXO评估板\LedShow\I2C.c
L3:
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile G:\Mega8程序\TCXO评估板\LedShow\I2C.c
.area text(rom, con, rel)
.dbfile G:\Mega8程序\TCXO评估板\LedShow\I2C.c
.dbfunc e TWI_Ready _TWI_Ready fV
.dbsym s charIndex L3 c
; charTemp -> R20
; TWI_STATE -> R22
.even
_TWI_Ready::
st -y,R2
st -y,R3
st -y,R16
st -y,R17
st -y,R24
st -y,R25
st -y,R30
st -y,R31
in R2,0x3f
st -y,R2
rcall push_gset2
.dbline -1
.dbline 91
; }
; #pragma interrupt_handler TWI_Ready:iv_TWI//TWI中断处理
; void TWI_Ready(void)
; {
.dbline 95
; static unsigned char charIndex=0;
; unsigned char charTemp;
; unsigned char TWI_STATE;
; TWI_STATE=TestAck();
in R22,0x1
andi R22,248
.dbline 96
; switch (TWI_STATE)//检查状态标志字
mov R20,R22
clr R21
cpi R20,160
ldi R30,0
cpc R21,R30
brne X2
rjmp L15
X2:
ldi R24,160
ldi R25,0
cp R24,R20
cpc R25,R21
brlt L20
L19:
cpi R20,96
ldi R30,0
cpc R21,R30
breq L7
cpi R20,96
ldi R30,0
cpc R21,R30
brge X3
rjmp L4
X3:
L21:
cpi R20,128
ldi R30,0
cpc R21,R30
breq L8
rjmp L4
L20:
cpi R20,184
ldi R30,0
cpc R21,R30
brne X4
rjmp L17
X4:
ldi R24,184
ldi R25,0
cp R24,R20
cpc R25,R21
brlt L23
L22:
cpi R20,168
ldi R30,0
cpc R21,R30
brne X5
rjmp L16
X5:
rjmp L4
L23:
cpi R20,192
ldi R30,0
cpc R21,R30
brne X6
rjmp L18
X6:
rjmp L4
X0:
.dbline 97
; {
L7:
.dbline 99
; case SR_SLA_ACK:
; {
.dbline 100
; MT_ACK;
ldi R24,197
out 0x36,R24
.dbline 101
; }
.dbline 102
; break;
rjmp L5
L8:
.dbline 104
; case SR_DATA_ACK:
; {
.dbline 105
; switch (charState)
lds R20,_charState
clr R21
cpi R20,80
ldi R30,0
cpc R21,R30
breq L13
cpi R20,80
ldi R30,0
cpc R21,R30
brge X7
rjmp L5
X7:
L14:
cpi R20,240
ldi R30,0
cpc R21,R30
breq L12
rjmp L5
X1:
.dbline 106
; {
L12:
.dbline 108
; case EE_READ://进入开始读取数据状态,此处即将读取的数据为ROM的Index
; {
.dbline 109
; PORTC^=(0b00001000);//闪亮LED
ldi R24,8
in R2,0x15
eor R2,R24
out 0x15,R2
.dbline 110
; charAddr=TWDR;
in R2,0x3
sts _charAddr,R2
.dbline 111
; MT_ACK;
ldi R24,197
out 0x36,R24
.dbline 112
; charState=EE_READ_OK;
ldi R24,80
sts _charState,R24
.dbline 113
; }
.dbline 114
; break;
rjmp L5
L13:
.dbline 116
; case EE_READ_OK://进入读取数据完成状态此处即将读取的数据为ROM->Index的数据
; {
.dbline 117
; charData=TWDR;
in R2,0x3
sts _charData,R2
.dbline 118
; MT_ACK;
ldi R24,197
out 0x36,R24
.dbline 120
; //rom_write((unsigned char)charAddr,charData);
; charState=EE_READ;
ldi R24,240
sts _charState,R24
.dbline 121
; charIndex+=3;
lds R24,L3
subi R24,253 ; addi 3
sts L3,R24
.dbline 122
; charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围
andi R24,31
sts L3,R24
.dbline 123
; cDataBuff[charIndex--]=0x0a;//间隔空格符
mov R2,R24
clr R3
subi R24,1
sts L3,R24
ldi R24,<_cDataBuff
ldi R25,>_cDataBuff
mov R30,R2
clr R31
add R30,R24
adc R31,R25
ldi R24,10
std z+0,R24
.dbline 124
; charTemp=charAddr%10;
ldi R17,10
lds R16,_charAddr
rcall mod8u
mov R20,R16
.dbline 125
; charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围
lds R24,L3
andi R24,31
sts L3,R24
.dbline 126
; cDataBuff[charIndex--]=charTemp;
mov R2,R24
clr R3
subi R24,1
sts L3,R24
ldi R24,<_cDataBuff
ldi R25,>_cDataBuff
mov R30,R2
clr R31
add R30,R24
adc R31,R25
std z+0,R20
.dbline 127
; charAddr/=10;
ldi R17,10
lds R16,_charAddr
rcall div8u
sts _charAddr,R16
.dbline 128
; charTemp=charAddr%10;
ldi R17,10
rcall mod8u
mov R20,R16
.dbline 129
; charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围
lds R24,L3
andi R24,31
sts L3,R24
.dbline 130
; cDataBuff[charIndex--]=charTemp;
mov R2,R24
clr R3
subi R24,1
sts L3,R24
ldi R24,<_cDataBuff
ldi R25,>_cDataBuff
mov R30,R2
clr R31
add R30,R24
adc R31,R25
std z+0,R20
.dbline 131
; charAddr/=10;
ldi R17,10
lds R16,_charAddr
rcall div8u
sts _charAddr,R16
.dbline 132
; cDataBuff[charIndex]=charAddr;
ldi R24,<_cDataBuff
ldi R25,>_cDataBuff
lds R30,L3
clr R31
add R30,R24
adc R31,R25
mov R2,R16
std z+0,R2
.dbline 133
; charIndex+=4;//指向末尾空位
lds R24,L3
subi R24,252 ; addi 4
sts L3,R24
.dbline 134
; charIndex+=3;
subi R24,253 ; addi 3
sts L3,R24
.dbline 135
; charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围
andi R24,31
sts L3,R24
.dbline 136
; cDataBuff[charIndex--]=0x0a;//间隔空格符
mov R2,R24
clr R3
subi R24,1
sts L3,R24
ldi R24,<_cDataBuff
ldi R25,>_cDataBuff
mov R30,R2
clr R31
add R30,R24
adc R31,R25
ldi R24,10
std z+0,R24
.dbline 137
; charTemp=charData%10;
ldi R17,10
lds R16,_charData
rcall mod8u
mov R20,R16
.dbline 138
; charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围
lds R24,L3
andi R24,31
sts L3,R24
.dbline 139
; cDataBuff[charIndex--]=charTemp;
mov R2,R24
clr R3
subi R24,1
sts L3,R24
ldi R24,<_cDataBuff
ldi R25,>_cDataBuff
mov R30,R2
clr R31
add R30,R24
adc R31,R25
std z+0,R20
.dbline 140
; charData/=10;
ldi R17,10
lds R16,_charData
rcall div8u
sts _charData,R16
.dbline 141
; charTemp=charData%10;
ldi R17,10
rcall mod8u
mov R20,R16
.dbline 142
; charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围
lds R24,L3
andi R24,31
sts L3,R24
.dbline 143
; cDataBuff[charIndex--]=charTemp;
mov R2,R24
clr R3
subi R24,1
sts L3,R24
ldi R24,<_cDataBuff
ldi R25,>_cDataBuff
mov R30,R2
clr R31
add R30,R24
adc R31,R25
std z+0,R20
.dbline 144
; charData/=10;
ldi R17,10
lds R16,_charData
rcall div8u
sts _charData,R16
.dbline 145
; cDataBuff[charIndex]=charData;
ldi R24,<_cDataBuff
ldi R25,>_cDataBuff
lds R30,L3
clr R31
add R30,R24
adc R31,R25
mov R2,R16
std z+0,R2
.dbline 146
; charIndex+=4;//指向末尾空位
lds R24,L3
subi R24,252 ; addi 4
sts L3,R24
.dbline 147
; }
.dbline 148
; break;
.dbline 150
; }
; }
.dbline 151
; break;
rjmp L5
L15:
.dbline 153
; case SR_STOP_RESTART://收到STOP信号或者RESTART
; {
.dbline 154
; MT_ACK;
ldi R24,197
out 0x36,R24
.dbline 155
; }
.dbline 156
; break;
rjmp L5
L16:
.dbline 158
; case ST_SLA_ACK://收到读信号,将(最后一个-NT_NACK、普通数据-MT_ACK)数据发送出去
; {
.dbline 161
; /*charTemp=rom_read((unsigned int)charAddr);
; TWDR=charTemp;*/
; TWDR=0xdd;//测试用,发送测试数据。MEGA8的EEPROM的读速度跟不上TWI
ldi R24,221
out 0x3,R24
.dbline 162
; MT_ACK;
ldi R24,197
out 0x36,R24
.dbline 163
; }
.dbline 164
; break;
rjmp L5
L17:
.dbline 166
; case ST_DATA_ACK://主机要求继续发送数据
; {
.dbline 167
; TWDR=cDataBuff[++charAddr];
lds R24,_charAddr
subi R24,255 ; addi 1
mov R2,R24
sts _charAddr,R2
ldi R24,<_cDataBuff
ldi R25,>_cDataBuff
mov R30,R2
clr R31
add R30,R24
adc R31,R25
ldd R2,z+0
out 0x3,R2
.dbline 168
; MT_ACK;
ldi R24,197
out 0x36,R24
.dbline 169
; }
.dbline 170
; break;
rjmp L5
L18:
.dbline 172
; case ST_DATA_NOACK://数据发送完毕
; {
.dbline 173
; MT_ACK;
ldi R24,197
out 0x36,R24
.dbline 174
; }
.dbline 175
; break;
rjmp L5
L4:
.dbline 177
.dbline 178
sts _charData,R22
.dbline 179
lds R24,L3
subi R24,253 ; addi 3
sts L3,R24
.dbline 180
andi R24,31
sts L3,R24
.dbline 181
mov R2,R24
clr R3
subi R24,1
sts L3,R24
ldi R24,<_cDataBuff
ldi R25,>_cDataBuff
mov R30,R2
clr R31
add R30,R24
adc R31,R25
ldi R24,11
std z+0,R24
.dbline 182
ldi R17,10
lds R16,_charData
rcall mod8u
mov R20,R16
.dbline 183
lds R24,L3
andi R24,31
sts L3,R24
.dbline 184
mov R2,R24
clr R3
subi R24,1
sts L3,R24
ldi R24,<_cDataBuff
ldi R25,>_cDataBuff
mov R30,R2
clr R31
add R30,R24
adc R31,R25
std z+0,R20
.dbline 185
ldi R17,10
lds R16,_charData
rcall div8u
sts _charData,R16
.dbline 186
ldi R17,10
rcall mod8u
mov R20,R16
.dbline 187
lds R24,L3
andi R24,31
sts L3,R24
.dbline 188
mov R2,R24
clr R3
subi R24,1
sts L3,R24
ldi R24,<_cDataBuff
ldi R25,>_cDataBuff
mov R30,R2
clr R31
add R30,R24
adc R31,R25
std z+0,R20
.dbline 189
ldi R17,10
lds R16,_charData
rcall div8u
sts _charData,R16
.dbline 190
ldi R24,<_cDataBuff
ldi R25,>_cDataBuff
lds R30,L3
clr R31
add R30,R24
adc R31,R25
mov R2,R16
std z+0,R2
.dbline 191
lds R24,L3
subi R24,252 ; addi 4
sts L3,R24
.dbline 192
ldi R24,197
out 0x36,R24
.dbline 193
.dbline 194
L5:
.dbline -2
L2:
rcall pop_gset2
ld R2,y+
out 0x3f,R2
ld R31,y+
ld R30,y+
ld R25,y+
ld R24,y+
ld R17,y+
ld R16,y+
ld R3,y+
ld R2,y+
.dbline 0 ; func end
reti
.dbsym r charTemp 20 c
.dbsym r TWI_STATE 22 c
.dbend
.area bss(ram, con, rel)
.dbfile G:\Mega8程序\TCXO评估板\LedShow\I2C.c
_charState::
.blkb 1
.dbsym e charState _charState c
_charAddr::
.blkb 1
.dbsym e charAddr _charAddr c
_charData::
.blkb 1
.dbsym e charData _charData c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -