请问马老师,AVR的TWI做主机是不是不能使用中断方式阿?
我用M16做主机,M8做从机(M8中断方式正常),当M16不使用中断方式正常。使用中断方式出现怪异的结果以下是我的测试程序(节选)
int main(void)
{
// 设波特率为9600
Init_UART(51);
// 设置看门狗
wdt_enable(WDTO_60MS);
// 允许睡眠模式
set_sleep_mode(0);
// TCCR0分频64
TCCR0 = 0x03;
// 开定时器0中断
//sbi(TIMSK,TOIE0);
// 设置TWI
TWBR = (CPU_CLOCK/SCL_CLK-16)/2;
PORTC |= 0x03;
// 允许全局中断
sei();
print("Start
");
gcSignal = 0;
TWI_TxHead = 0;TWI_RxHead = 0;TWI_TxTail = 0;TWI_RxTail = 0;
unsigned char ascii = {0,0,0};
while(1)
{
wdt_reset();
if(bit_is_set(gcSignal, UART_RECEIVED))
{
cbi(gcSignal, UART_RECEIVED);
TransmitByte(UART_RxBuf);print("
"); //回显
TWI_Send_Byte(UART_RxBuf);
UART_RxHead = (UART_RxHead + 1) & UART_RX_BUFFER_MASK;
}
if(bit_is_set(gcSignal, TWI_RECEIVED))
{
cbi(gcSignal, TWI_RECEIVED);
print("TWSR = ");char_to_ascii(gcTWSR, ascii);print(ascii);print("
");
switch(gcTWSR)
{
case TW_START: //0x08
if(gcTWI_State == TWI_START)
{
gcTWI_State = TWI_SLA_W;
TWDR = 0x02 | TW_WRITE;
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
}
break;
case TW_REP_START: //0x10
if(gcTWI_State == TWI_START)
{
gcTWI_State = TWI_SLA_W;
TWDR = 0x02 | TW_WRITE;
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
}
break;
case TW_MT_SLA_ACK: //0x18
if(gcTWI_State == TWI_SLA_W)
{
gcTWI_State = TWI_DATA_W;
TWI_TxTail = (TWI_TxTail + 1) & TWI_TX_BUFFER_MASK;
TWDR = TWI_TxBuf;
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
}
break;
case TW_MT_SLA_NACK: //0x20
if(gcTWI_State == TWI_SLA_W)
{
gcTWI_State = TWI_DATA_W;
TWI_TxTail = (TWI_TxTail + 1) & TWI_TX_BUFFER_MASK;
TWDR = TWI_TxBuf;
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
}
break;
case TW_MT_DATA_ACK: //0x28
if(gcTWI_State == TWI_DATA_W)
{
gcTWI_State = TWI_STOP;
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE) | (1<<TWSTO);
}
break;
case TW_MT_DATA_NACK: //0x30
if(gcTWI_State == TWI_DATA_W)
{
gcTWI_State = TWI_STOP;
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE) | (1<<TWSTO);
}
break;
case TW_MR_SLA_ACK: //0x40
break;
case TW_MR_SLA_NACK: //0x48
break;
case TW_MR_DATA_ACK: //0x50
break;
case TW_MR_DATA_NACK: //0x58
break;
case TW_NO_INFO: //0xF8
break;
default:
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE) | (1<<TWSTO);
}
}
}
}
SIGNAL(SIG_UART_DATA)
{
/* check if all data is transmitted */
if(UART_TxHead != UART_TxTail )
{
/* calculate buffer index */
UART_TxTail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
UDR = UART_TxBuf; /* start transmition */
}
else cbi(UCSRB,UDRIE); // disable UDR interrupt
}
SIGNAL(SIG_UART_RECV)
{
unsigned char cReceivedByte;
cReceivedByte = UDR;
UART_RxBuf = cReceivedByte;
UART_RxTail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
sbi(gcSignal, UART_RECEIVED);
}
SIGNAL(SIG_2WIRE_SERIAL)
{
gcTWSR = TWSR;
sbi(gcSignal, TWI_RECEIVED);
}
-----此内容被Tomcat于2005-05-22,12:11:12编辑过
-----此内容被Tomcat于2005-05-22,12:40:36编辑过 测试程序的流程是当从串口接受到一个字符时,回显字符并传输该字符到TWI口,TWI中断后打印TWSR的值再判断作什么处理
当收到一个字符并发送到TWI理想的结果应该是回显(假设输入的字符是'g')
Start
g
TWSR = 08
TWSR = 18
TWSR = 28
但是当中断服务程序为这样时
SIGNAL(SIG_2WIRE_SERIAL)
{
gcTWSR = TWSR;
sbi(gcSignal, TWI_RECEIVED);
TWCR = 1<<TWINT; // 清TWINT
}
回显
Start
g
TWSR = 08 //没动静了,再敲键盘也是同样的结果
当中断服务程序这样时
SIGNAL(SIG_2WIRE_SERIAL)
{
gcTWSR = TWSR;
sbi(gcSignal, TWI_RECEIVED);
cbi(TWCR, TWIE);// 禁止TWI中断
}
Start
d //我敲的字符
TWSR = 08
TWSR = 48//TWSR的值居然是0x48,搞不懂
d
TWSR = 10
TWSR = 48
d
TWSR = 10
TWSR = 48
写成这样,中断程序对TWI不作任何处理
SIGNAL(SIG_2WIRE_SERIAL)
{
gcTWSR = TWSR;
sbi(gcSignal, TWI_RECEIVED);
}
串口回送
Start
d
TWSR = 08
TWSR = F8
TWSR = 18
TWSR = F8
TWSR = 28
TWSR = F8
d
TWSR = 08
TWSR = F8
TWSR = 18
TWSR = F8
TWSR = 28
TWSR = F8
还算正常,可以用,但是由于TWINT还是1,TWI中断也没有屏蔽,TWI一直在不停的中断,程序效率很低
我不知道哪里错了,搞了3天,快崩溃了。怀疑是不是AVR TWI有Bug,不过这种事一般都是我出错。我在网上查了半天,好像没人用TWI的主机中断方式,都是等待。
马老师如果有空的时候帮看看吧,要是忙就直接删了,不想太麻烦你
谢谢! 我也想问这个问题:AVR的TWI做主机是不是不能使用中断方式阿 请参考《M128》书中第五章的例子,里面有关于TWI主机的参考,使用中断+状态机+数据缓冲器。
页:
[1]