2014-03-31 42 views
-1

我通過外部中斷在軟件uart上有這段代碼。任何人都可以請檢查這是什麼問題?它可以在位移位的引腳上傳輸,但它不傳輸所需的值。這是代碼。通過外部中斷軟件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; 
     } 
    } 
} 
+0

大多數UART都是低電平有效。你的看起來很活躍。你有沒有示波器來檢查你發送的數據是你期望的? –

+0

活躍的高與低是一個重要的問題 - 但記住線路驅動因素也是傳統上反轉的,所以它關係到什麼是連接。另一個問題是如果錯誤的字符是可靠和一致的傳輸,如果是的話,如果你可以提供一些預期字符與實際接收到的字符的映射的例子。 –

+0

你可以編輯我的代碼嗎? – jbat21

回答

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; 
} 
+0

這不起作用。 – jbat21

+0

有一件事你錯了,就是這樣的東西。 TIMSK1 =(0 << OCIE1B); TIMSK1是一個8位寄存器。我想要做的是將OCIE1B位設置爲0x00(零十六進制)。問題是,(0 << OCIE1B)編譯爲0x00。 在AVR處理器上工作的結構是, TIMSK1 =(0 << OCIE1B); – Gibbon1