📄 twi.s
字号:
.module twi.c
.area text(rom, con, rel)
.dbfile E:\avr\twi\twi_master_test\twi.c
.dbfunc e twi_master_init _twi_master_init fV
.even
_twi_master_init::
.dbline -1
.dbline 10
; // 作者:古欣
; // AVR与虚拟仪器 http://www.avrvi.com
; #include "config.h"
;
; //注意本文件和从机的文件不同
;
; //TWI master initialize
; // bit rate:100
; void twi_master_init(void)
; {
.dbline 11
; TWCR= 0x00; //disable twi
clr R2
out 0x36,R2
.dbline 12
; TWBR= 0x64; //set bit rate
ldi R24,100
out 0x0,R24
.dbline 13
; TWSR= 0x00; //set prescale
out 0x1,R2
.dbline 14
; TWAR= 0x00; //set slave address
out 0x2,R2
.dbline 15
; TWCR= 0x04; //enable twi
ldi R24,4
out 0x36,R24
.dbline -2
L1:
.dbline 0 ; func end
ret
.dbend
.dbfunc e twi_slave_init _twi_slave_init fV
; add -> R16
.even
_twi_slave_init::
.dbline -1
.dbline 21
; }
;
; //TWI slave initialize
; // bit rate:100
; void twi_slave_init(uint8 add)
; {
.dbline 22
; TWCR= 0x00; //disable twi
clr R2
out 0x36,R2
.dbline 23
; TWBR= 0x64; //set bit rate
ldi R24,100
out 0x0,R24
.dbline 24
; TWSR= 0x00; //set prescale
out 0x1,R2
.dbline 25
; TWAR= (add<<1); //set slave address 从机地址为 0x01
mov R2,R16
lsl R2
out 0x2,R2
.dbline 26
; TWCR= (1<<TWEN)|(1<<TWEA)|(1<<TWIE); //enable twi
ldi R24,69
out 0x36,R24
.dbline -2
L2:
.dbline 0 ; func end
ret
.dbsym r add 16 c
.dbend
.dbfunc e i2c_start _i2c_start fV
.even
_i2c_start::
.dbline -1
.dbline 32
; //TWEN必须置位以使能TWI接口。TWEA也要置位以使主机寻址到自己(从机地址或广播) 时返回确认信息ACK
; }
;
; //总线上起动开始条件
; void i2c_start(void)
; {
.dbline 33
; TWCR= (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
ldi R24,164
out 0x36,R24
L4:
.dbline 34
L5:
.dbline 34
; while (!(TWCR & (1<<TWINT))); //等待START 信号成功发送
in R2,0x36
sbrs R2,7
rjmp L4
.dbline -2
L3:
.dbline 0 ; func end
ret
.dbend
.dbfunc e i2c_write_addr _i2c_write_addr fc
; r_w -> R18
; addr -> R16
.even
_i2c_write_addr::
.dbline -1
.dbline 40
; }
;
; //把一个字节数据输入器件, 返回TWI状态
; //发送地址,r_w:1为读,0为写
; uint8 i2c_write_addr(uint8 addr,uint8 r_w)
; {
.dbline 41
; if(r_w)
tst R18
breq L8
.dbline 42
; {
.dbline 43
; TWDR = addr|r_w; //RW 为1:读操作
mov R2,R16
or R2,R18
out 0x3,R2
.dbline 44
; }
xjmp L9
L8:
.dbline 46
; else
; {
.dbline 47
; TWDR = addr & 0xFE; // RW 为0: 写操作
mov R24,R16
andi R24,254
out 0x3,R24
.dbline 48
; }
L9:
.dbline 50
;
; TWCR = (1<<TWINT)|(1<<TWEN);
ldi R24,132
out 0x36,R24
L10:
.dbline 51
L11:
.dbline 51
; while (!(TWCR & (1<<TWINT)));
in R2,0x36
sbrs R2,7
rjmp L10
.dbline 52
; _NOP();
nop
.dbline 53
; return(TWSR&0b11111000); //TWSR高五位为I2C工作状态。
in R16,0x1
andi R16,248
.dbline -2
L7:
.dbline 0 ; func end
ret
.dbsym r r_w 18 c
.dbsym r addr 16 c
.dbend
.dbfunc e i2c_write_data _i2c_write_data fc
; data -> R16
.even
_i2c_write_data::
.dbline -1
.dbline 59
; }
;
; //把一个字节数据输入器件, 返回TWI状态
; //发送数据
; uint8 i2c_write_data(uint8 data)
; {
.dbline 60
; TWDR = data;
out 0x3,R16
.dbline 61
; TWCR = (1<<TWINT)|(1<<TWEN);
ldi R24,132
out 0x36,R24
L14:
.dbline 62
L15:
.dbline 62
; while (!(TWCR & (1<<TWINT)));
in R2,0x36
sbrs R2,7
rjmp L14
.dbline 63
; _NOP();
nop
.dbline 64
; return(TWSR&0b11111000); //TWSR高五位为I2C工作状态。
in R16,0x1
andi R16,248
.dbline -2
L13:
.dbline 0 ; func end
ret
.dbsym r data 16 c
.dbend
.dbfunc e i2c_read _i2c_read fc
.even
_i2c_read::
.dbline -1
.dbline 70
; }
;
;
; //从器件读出一个字节
; uint8 i2c_read(void)
; {
.dbline 71
; TWCR = (1<<TWINT)|(1<<TWEN);
ldi R24,132
out 0x36,R24
.dbline 72
; Twi_NoAcK();
.dbline 72
in R24,0x36
andi R24,15
ori R24,128
out 0x36,R24
.dbline 72
.dbline 72
L18:
.dbline 73
L19:
.dbline 73
; while (!(TWCR & (1<<TWINT)));
in R2,0x36
sbrs R2,7
rjmp L18
.dbline 74
; return(TWDR);
in R16,0x3
.dbline -2
L17:
.dbline 0 ; func end
ret
.dbend
.dbfunc e i2c_stop _i2c_stop fV
.even
_i2c_stop::
.dbline -1
.dbline 79
; }
;
; //总线上起动停止条件
; void i2c_stop(void)
; {
.dbline 80
; TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
ldi R24,148
out 0x36,R24
.dbline -2
L21:
.dbline 0 ; func end
ret
.dbend
.dbfunc e i2c_maste_transt _i2c_maste_transt fV
; data -> R20
; addr -> R22
.even
_i2c_maste_transt::
xcall push_gset2
mov R20,R18
mov R22,R16
.dbline -1
.dbline 85
; }
;
; //操作步骤: 启动,发送地址,发送数据,关闭总线
; void i2c_maste_transt(uint8 addr, uint8 data)
; {
.dbline 86
; i2c_start();
xcall _i2c_start
.dbline 88
;
; if(i2c_write_addr(addr, 0)==TW_MT_SLA_ACK) //发送地址成功并收到ACK
clr R18
mov R16,R22
xcall _i2c_write_addr
cpi R16,24
brne L23
.dbline 89
; {
.dbline 90
; i2c_write_data(data);
mov R16,R20
xcall _i2c_write_data
.dbline 91
; }
L23:
.dbline 92
; i2c_stop();
xcall _i2c_stop
.dbline -2
L22:
xcall pop_gset2
.dbline 0 ; func end
ret
.dbsym r data 20 c
.dbsym r addr 22 c
.dbend
.dbfunc e i2c_maste_read _i2c_maste_read fc
; tmp -> R20
; addr -> R22
.even
_i2c_maste_read::
xcall push_gset2
mov R22,R16
.dbline -1
.dbline 96
; }
; //操作步骤,启动,发送地址,读数据,关闭总线
; uint8 i2c_maste_read(uint8 addr)
; {
.dbline 97
; uint8 tmp=0;
clr R20
.dbline 98
; i2c_start();
xcall _i2c_start
.dbline 99
; if(i2c_write_addr(addr, 1)==TW_MR_SLA_ACK) //发送地址成功并收到ACK
ldi R18,1
mov R16,R22
xcall _i2c_write_addr
cpi R16,64
brne L26
.dbline 100
; {
.dbline 101
; tmp=i2c_read();
xcall _i2c_read
mov R20,R16
.dbline 102
; }
L26:
.dbline 103
; i2c_stop();
xcall _i2c_stop
.dbline 104
; return tmp;
mov R16,R20
.dbline -2
L25:
xcall pop_gset2
.dbline 0 ; func end
ret
.dbsym r tmp 20 c
.dbsym r addr 22 c
.dbend
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -