软件UART通过外部中断

时间:2014-03-31 00:06:50

标签: c avr-gcc

我通过外部中断在软件uart上有这个代码。任何人都可以检查这是什么问题?它可以在位爆炸引脚上传输但不传输所需的值。这是代码。

/*
 * MidtermSUART.c
 *
 * Created: 3/31/2014 5:11:08 AM
 *  Author: johnmark
 */ 


#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
#include <math.h>


#define TRXDDR  DDRD
#define TRXPORT PORTD
#define TRXPIN  PIND
#define TX_PIN  PIND3               //Transmit data pin
#define RX_PIN  PIND2               //Receive data pin
#define SET_TX_PIN()    ( TRXPORT |= ( 1 << TX_PIN ) )
#define CLEAR_TX_PIN()  ( TRXPORT &= ~( 1 << TX_PIN ) )
#define GET_RX_PIN()    ( TRXPIN & ( 1 << RX_PIN ) )

#define ENABLE_EXTERNAL0_INTERRUPT()   ( EIMSK |= ( 1<< INT0 ) )
#define DISABLE_EXTERNAL0_INTERRUPT()  ( EIMSK = ( 0<< INT0 ) )

volatile unsigned char pinchange = 0xFF;
volatile char received = 0;
volatile char transmit = 0;
volatile int i = 0;
volatile int j = 0;
volatile int confirm = 0;
//Initialize Software Uart
void SUART_Init()
{
    TRXDDR |= ( 1 << TX_PIN );        // TX_PIN is output.
    SET_TX_PIN( );                    // Set the TX line to idle state.

    TCCR1A = 0;     // set entire TCCR1A register to 0
    TCCR1B = 0;     // same for TCCR1B
    // turn on CTC mode:
    TCCR1B |= (1 << WGM12);
    // Set CS10 bit for 1 pre-scaler:
    TCCR1B |= (1 << CS10);
    TCNT1  = 0;
    // set compare match register to desired timer count:
    OCR1A = round(16000000/(9600));
    OCR1B = round(16000000/(9600));
    //ENABLE_EXTERNAL0_INTERRUPT();
    EIMSK = (1<<INT0); 
}
//Receiving Section
ISR(INT0_vect)
{
    // enable timer compare interrupt:
    TIMSK1 |= (1 << OCIE1A); //Enable Output Compare A Match Interrupt 
    //DISABLE_EXTERNAL0_INTERRUPT();
    EIMSK = 0;
    //PCICR = (0 << PCIE0); //Pin Change Interrupt Enable 0
    TCNT1  = 0;  

}
//receive
ISR(TIMER1_COMPA_vect)
{
    if (i >= 1) {
    received |= ((PIND&0x04)>>2)<<(i-1);
    }
    i++;
    if (i == 10)
    {
        i = 0;
        //ENABLE_EXTERNAL0_INTERRUPT();
        EIMSK = (1<<INT0);
        TIMSK1 = (0 << OCIE1A); 
        TCNT1  = 0;
        confirm = 1;
    }

}
//transmit
ISR(TIMER1_COMPB_vect)
{
    if (j == 0) 
    {
        PORTD = (0<<PIND3);
    }
    if ((j > 0)&&(j < 9))
    {
        PORTD = ((transmit>>(j-1))&0x01)<<PIND3;
    }
    j++;
    if (j == 10)
    {
        PORTD = (1<<PIND3);
        TIMSK1 = (0 << OCIE1B);
        j = 0;
        TCNT1  = 0;
    }       
}

void SWUART_send(char m)
{
    transmit = m;
    TIMSK1 |= (1 << OCIE1B);
    TCNT1  = 0;
}

int main (void)
{
    SUART_Init();
    sei();          // enable global interrupts
    while(1)
    {
        //TODO:: Please write your application code
        if (confirm == 1)
        {
            //UART_send(x);
            SWUART_send(received);
            received = 0;
            confirm = 0;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

if (j == 0) 
{
    PORTD = (0<<PIND3);
}
if ((j > 0)&&(j < 9))
{
    PORTD = ((transmit>>(j-1))&0x01)<<PIND3;
}

这段代码有问题...... 可能不是唯一的问题,但通常在您设置端口位时使用AVR编码。你这样做。

PORTD |= (1<<PIND3);  // set PORTD bit 3
PORTD &= ~(1<<PIND3);  // clears PORTD bit 3

尝试这样的事情。

if (j == 0) 
{
    // start bit
    PORTD &= ~(1<<PIND3);
}
else if ((j > 0)&&(j < 9))
{
    // shift data out
    if( (transmit>>(j-1)) &0x01)
        PORTD |= (1<<PIND3);
    else
        PORTD &= (1<<PIND3);
}

j++;
if (j == 10)
{
    // stop bit
    PORTD |= (1<<PIND3);

    // timer off
    TIMSK1 = (0 << OCIE1B);
    j = 0;
    TCNT1  = 0;
}