共4条
1/1 1 跳转至页
mega8,I2C 高手指点一下mega8的I2C,不胜感激
问
为什么I2C置标志置位进不了中断,定时器,外中断都可以,是我弄错了,还是怎么回事,烦请高手指点,以及其注意事项,谢谢
答 1: slaver or master? 答 2: 都是这样啊 ldi temp,0x20 ;设置波特率
out TWBR,temp
ldi temp,0x00
out TWSR,temp
主机,我用查询方式
ldi r16, (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
out TWCR, r16
wait1:
in r16,TWCR
sbrs r16,TWINT
rjmp wait1
in r16,TWSR
andi r16, 0xF8
cpi r16, 0x08
brne ERROR
ldi r16, 0x02
out TWDR, r16
ldi r16, (1<<TWINT) | (1<<TWEN)
out TWCR, r16
wait2:
in r16,TWCR
sbrs r16,TWINT
rjmp wait2
in r16,TWSR
andi r16, 0xF8
cpi r16, 0x18
brne ERROR
ldi r16, 0xff
out TWDR, r16
ldi r16, (1<<TWINT) | (1<<TWEN)
out TWCR, r16
wait3:
in r16,TWCR
sbrs r16,TWINT
rjmp wait3
in r16,TWSR
andi r16, 0xF8
cpi r16, 0x28
brne ERROR
ldi r16, (1<<TWINT)|(1<<TWEN)|(1<<TWSTO)
out TWCR, r16
error: rjmp error
从机中断
ldi temp,SLA ;从机地址
out TWAR,temp
ldi temp,(1<<TWEN)|(1<<TWIE)|(TWEA);开I2中断
out TWCR,temp
sei
wait1: sbrs bvalid,0
rjmp wait1
clr bvalid
tt: rjmp tt
I2int: cbi PORTB,0
kk: rjmp kk
in temp,TWSR ;检测TWI状态寄存器TWSR,屏蔽预分频位
andi temp,0xf8
cpi temp,0x60 ;如果不是SLA+W转移
brne end
ldi temp,(1<<TWINT)|(1<<TWEA)
out TWCR,temp
wait2: in temp,TWCR
sbrs temp,TWINT
rjmp wait2 ;等待TWINT置位
in temp,TWSR
andi temp,0xf8
cpi temp,0x88 ;如果不是SLA+W寻址,DATA已经收到,NACK已经发出,转移
brne end
in MOrder,TWDR ;读出主机命令
clr temp
out TWCR,temp
ldi temp,Time1_scaler ;开定时器
out TCCR1B,temp
ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN);转入被控初始状态,进行本机SLA匹配
out TWCR,temp
wait3: in temp,TWCR
sbrs temp,TWINT
rjmp wait3
in temp,TWSR
andi temp,0xf8
cpi temp,0xa8 ;收到本机SLA+R,ACK已经发出
brne end
out TWDR,MOrder ;发送刚刚受到的命令
ldi temp,(1<<TWINT)|(1<<TWEN);发送最后一个DATA,接收NACK信号
out TWCR,temp
wait4: in temp,TWCR
sbrs temp,TWINT
rjmp wait4
in temp,TWSR
andi temp,0xf8
cpi temp,0xc0 ;如果不是DATA已经发出,受到NACK信号,转移
brne end
ldi temp,(1<<TWINT)|(1<<TWEA);转入被控初始状态,进行本机SLA匹配
out TWCR,temp
call delay
wait5: sbic PINB,OK ;等待主机应答信号
rjmp wait5
cbi PORTB,Answer ;应答主机
call delay
sbi PORTB,Answer
sbr bvalid,0x01
end: clr temp
out TWCR,temp
reti
开始我主机也是用的中断,不行,我又改为查询方式
还是不行,资料上都说写1清TWINT,但是我用软件
仿真是清不掉的,怎么回事??
答 3: 这是我从程序中拷出来的,实际中肯定能用 ; *** Init I2C ***
outi twbr,(ck-16*sclk)/(2*sclk) ; i2c clock
.equ START = 0x8
.equ MT_SLA_ACK = 0x18
.equ MT_DATA_ACK = 0x28
.equ MR_SLA_ACK = 0x40
.equ MR_DATA_ACK = 0x50
.equ MR_DATA_NACK = 0x58
;************************************
; i2c write, write a string
; entry: iicadd, iicnumber-- numbers to be write, X-- data pointer
; exit: c=0 ok; c=1 failed
;***********************************
i2cwr:
outi TWCR,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN) ; i2c start
in r16,TWCR
sbrs r16,TWINT
rjmp pc-2 ; waite
in r16,TWSR
andi r16,0xf8 ; mask prescale bits
cpi r16,START ; if start?
brne error
out TWDR,iicadd ; write i2c device address
sts lastadd,iicadd
cbi TWDR,0 ; i2c write
outi TWCR,(1<<TWINT)|(1<<TWEN) ;
in r16,TWCR
sbrs r16,TWINT
rjmp pc-2 ; waite
in r16,TWSR
andi r16,0xf8 ; mask prescale bits
cpi r16,MT_SLA_ACK ; if address ack?
brne error
i2cwr_lp:
ld r16,x+ ; get data
out TWDR,r16
outi TWCR,(1<<TWINT)|(1<<TWEN) ;
in r16,TWCR
sbrs r16,TWINT
rjmp pc-2 ; waite
in r16,TWSR
andi r16,0xf8 ; mask prescale bits
cpi r16,MT_DATA_ACK ; if data ack?
brne error
dec iicnumber
brne i2cwr_lp
outi TWCR,(1<<TWINT)|(1<<TWSTO)|(1<<TWEN) ; i2c stop
clc
ret
error: sec
ret
;*********************************************
; i2c read, only read one byte
; entry: iicadd
; exit: r16--data, c=0 ok; c=1 failed
;*********************************************
i2crd:
outi TWCR,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN) ; i2c start
in r16,TWCR
sbrs r16,TWINT
rjmp pc-2 ; waite
in r16,TWSR
andi r16,0xf8 ; mask prescale bits
cpi r16,START ; if start?
brne error
out TWDR,iicadd ; write i2c device address
sbi TWDR,0 ; i2c read
outi TWCR,(1<<TWINT)|(1<<TWEN) ;
in r16,TWCR
sbrs r16,TWINT
rjmp pc-2 ; waite
in r16,TWSR
andi r16,0xf8 ; mask prescale bits
cpi r16,MR_SLA_ACK ; if address ack?
brne error
outi TWCR,(1<<TWINT)|(1<<TWEN) ;
in r16,TWCR
sbrs r16,TWINT
rjmp pc-2 ; waite
in r16,TWSR
andi r16,0xf8 ; mask prescale bits
cpi r16,MR_DATA_NACK ; if final data?
brne error
in r16,TWDR
push r16
outi TWCR,(1<<TWINT)|(1<<TWSTO)|(1<<TWEN) ; i2c stop
pop r16
clc
ret
答 4: 补充一下OUTI的宏定义:; Output immediate
;
; outi port,var
.macro outi
ldi r16,@1
out @0,r16
.endm
答 5: 多谢指点,问题已经搞定
答 1: slaver or master? 答 2: 都是这样啊 ldi temp,0x20 ;设置波特率
out TWBR,temp
ldi temp,0x00
out TWSR,temp
主机,我用查询方式
ldi r16, (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
out TWCR, r16
wait1:
in r16,TWCR
sbrs r16,TWINT
rjmp wait1
in r16,TWSR
andi r16, 0xF8
cpi r16, 0x08
brne ERROR
ldi r16, 0x02
out TWDR, r16
ldi r16, (1<<TWINT) | (1<<TWEN)
out TWCR, r16
wait2:
in r16,TWCR
sbrs r16,TWINT
rjmp wait2
in r16,TWSR
andi r16, 0xF8
cpi r16, 0x18
brne ERROR
ldi r16, 0xff
out TWDR, r16
ldi r16, (1<<TWINT) | (1<<TWEN)
out TWCR, r16
wait3:
in r16,TWCR
sbrs r16,TWINT
rjmp wait3
in r16,TWSR
andi r16, 0xF8
cpi r16, 0x28
brne ERROR
ldi r16, (1<<TWINT)|(1<<TWEN)|(1<<TWSTO)
out TWCR, r16
error: rjmp error
从机中断
ldi temp,SLA ;从机地址
out TWAR,temp
ldi temp,(1<<TWEN)|(1<<TWIE)|(TWEA);开I2中断
out TWCR,temp
sei
wait1: sbrs bvalid,0
rjmp wait1
clr bvalid
tt: rjmp tt
I2int: cbi PORTB,0
kk: rjmp kk
in temp,TWSR ;检测TWI状态寄存器TWSR,屏蔽预分频位
andi temp,0xf8
cpi temp,0x60 ;如果不是SLA+W转移
brne end
ldi temp,(1<<TWINT)|(1<<TWEA)
out TWCR,temp
wait2: in temp,TWCR
sbrs temp,TWINT
rjmp wait2 ;等待TWINT置位
in temp,TWSR
andi temp,0xf8
cpi temp,0x88 ;如果不是SLA+W寻址,DATA已经收到,NACK已经发出,转移
brne end
in MOrder,TWDR ;读出主机命令
clr temp
out TWCR,temp
ldi temp,Time1_scaler ;开定时器
out TCCR1B,temp
ldi temp,(1<<TWINT)|(1<<TWEA)|(1<<TWEN);转入被控初始状态,进行本机SLA匹配
out TWCR,temp
wait3: in temp,TWCR
sbrs temp,TWINT
rjmp wait3
in temp,TWSR
andi temp,0xf8
cpi temp,0xa8 ;收到本机SLA+R,ACK已经发出
brne end
out TWDR,MOrder ;发送刚刚受到的命令
ldi temp,(1<<TWINT)|(1<<TWEN);发送最后一个DATA,接收NACK信号
out TWCR,temp
wait4: in temp,TWCR
sbrs temp,TWINT
rjmp wait4
in temp,TWSR
andi temp,0xf8
cpi temp,0xc0 ;如果不是DATA已经发出,受到NACK信号,转移
brne end
ldi temp,(1<<TWINT)|(1<<TWEA);转入被控初始状态,进行本机SLA匹配
out TWCR,temp
call delay
wait5: sbic PINB,OK ;等待主机应答信号
rjmp wait5
cbi PORTB,Answer ;应答主机
call delay
sbi PORTB,Answer
sbr bvalid,0x01
end: clr temp
out TWCR,temp
reti
开始我主机也是用的中断,不行,我又改为查询方式
还是不行,资料上都说写1清TWINT,但是我用软件
仿真是清不掉的,怎么回事??
答 3: 这是我从程序中拷出来的,实际中肯定能用 ; *** Init I2C ***
outi twbr,(ck-16*sclk)/(2*sclk) ; i2c clock
.equ START = 0x8
.equ MT_SLA_ACK = 0x18
.equ MT_DATA_ACK = 0x28
.equ MR_SLA_ACK = 0x40
.equ MR_DATA_ACK = 0x50
.equ MR_DATA_NACK = 0x58
;************************************
; i2c write, write a string
; entry: iicadd, iicnumber-- numbers to be write, X-- data pointer
; exit: c=0 ok; c=1 failed
;***********************************
i2cwr:
outi TWCR,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN) ; i2c start
in r16,TWCR
sbrs r16,TWINT
rjmp pc-2 ; waite
in r16,TWSR
andi r16,0xf8 ; mask prescale bits
cpi r16,START ; if start?
brne error
out TWDR,iicadd ; write i2c device address
sts lastadd,iicadd
cbi TWDR,0 ; i2c write
outi TWCR,(1<<TWINT)|(1<<TWEN) ;
in r16,TWCR
sbrs r16,TWINT
rjmp pc-2 ; waite
in r16,TWSR
andi r16,0xf8 ; mask prescale bits
cpi r16,MT_SLA_ACK ; if address ack?
brne error
i2cwr_lp:
ld r16,x+ ; get data
out TWDR,r16
outi TWCR,(1<<TWINT)|(1<<TWEN) ;
in r16,TWCR
sbrs r16,TWINT
rjmp pc-2 ; waite
in r16,TWSR
andi r16,0xf8 ; mask prescale bits
cpi r16,MT_DATA_ACK ; if data ack?
brne error
dec iicnumber
brne i2cwr_lp
outi TWCR,(1<<TWINT)|(1<<TWSTO)|(1<<TWEN) ; i2c stop
clc
ret
error: sec
ret
;*********************************************
; i2c read, only read one byte
; entry: iicadd
; exit: r16--data, c=0 ok; c=1 failed
;*********************************************
i2crd:
outi TWCR,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN) ; i2c start
in r16,TWCR
sbrs r16,TWINT
rjmp pc-2 ; waite
in r16,TWSR
andi r16,0xf8 ; mask prescale bits
cpi r16,START ; if start?
brne error
out TWDR,iicadd ; write i2c device address
sbi TWDR,0 ; i2c read
outi TWCR,(1<<TWINT)|(1<<TWEN) ;
in r16,TWCR
sbrs r16,TWINT
rjmp pc-2 ; waite
in r16,TWSR
andi r16,0xf8 ; mask prescale bits
cpi r16,MR_SLA_ACK ; if address ack?
brne error
outi TWCR,(1<<TWINT)|(1<<TWEN) ;
in r16,TWCR
sbrs r16,TWINT
rjmp pc-2 ; waite
in r16,TWSR
andi r16,0xf8 ; mask prescale bits
cpi r16,MR_DATA_NACK ; if final data?
brne error
in r16,TWDR
push r16
outi TWCR,(1<<TWINT)|(1<<TWSTO)|(1<<TWEN) ; i2c stop
pop r16
clc
ret
答 4: 补充一下OUTI的宏定义:; Output immediate
;
; outi port,var
.macro outi
ldi r16,@1
out @0,r16
.endm
答 5: 多谢指点,问题已经搞定
共4条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
vscode+cmake搭建雅特力AT32L021开发环境被打赏30分 | |
【换取逻辑分析仪】自制底板并驱动ArduinoNanoRP2040ConnectLCD扩展板被打赏47分 | |
【分享评测,赢取加热台】RISC-V GCC 内嵌汇编使用被打赏38分 | |
【换取逻辑分析仪】-基于ADI单片机MAX78000的简易MP3音乐播放器被打赏48分 | |
我想要一部加热台+树莓派PICO驱动AHT10被打赏38分 | |
【换取逻辑分析仪】-硬件SPI驱动OLED屏幕被打赏36分 | |
换逻辑分析仪+上下拉与多路选择器被打赏29分 | |
Let'sdo第3期任务合集被打赏50分 | |
换逻辑分析仪+Verilog三态门被打赏27分 | |
换逻辑分析仪+Verilog多输出门被打赏24分 |