共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电子工程师创研计划】技术变现通道已开启~ | |
发原创文章 【每月瓜分千元赏金 凭实力攒钱买好礼~】 | |
【EEPW在线】E起听工程师的声音! | |
“我踩过的那些坑”主题活动——第001期 | |
高校联络员开始招募啦!有惊喜!! | |
【工程师专属福利】每天30秒,积分轻松拿!EEPW宠粉打卡计划启动! | |
送您一块开发板,2025年“我要开发板活动”又开始了! | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
电流检测模块MAX4080S被打赏10分 | |
【我踩过的那些坑】calloc和malloc错误使用导致跑飞问题排查被打赏50分 | |
多组DCTODC电源方案被打赏50分 | |
【我踩过的那些坑】STM32cubeMX软件的使用过程中的“坑”被打赏50分 | |
新手必看!C语言精华知识:表驱动法被打赏50分 | |
【我踩过的那些坑】杜绑线问题被打赏50分 | |
【我踩过的那些坑】STM32的硬件通讯调试过程的“坑”被打赏50分 | |
【我踩过的那些坑】晶振使用的问题被打赏100分 | |
【我踩过的那些坑】电感选型错误导致的处理器连接不上被打赏50分 | |
【我踩过的那些坑】工作那些年踩过的记忆深刻的坑被打赏10分 |