Tomcat 发表于 2005-5-22 12:10:43

请问马老师,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编辑过

Tomcat 发表于 2005-5-22 12:37:18

测试程序的流程是当从串口接受到一个字符时,回显字符并传输该字符到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的主机中断方式,都是等待。



马老师如果有空的时候帮看看吧,要是忙就直接删了,不想太麻烦你



谢谢!

tarzar 发表于 2005-6-17 15:52:27

我也想问这个问题:AVR的TWI做主机是不是不能使用中断方式阿

machao 发表于 2005-6-18 18:53:32

请参考《M128》书中第五章的例子,里面有关于TWI主机的参考,使用中断+状态机+数据缓冲器。
页: [1]
查看完整版本: 请问马老师,AVR的TWI做主机是不是不能使用中断方式阿?