2015-12-20 6 views
0

Я пытаюсь создать программу C, которая получает символ через UART, «печатает» соответствующий бинарный файл, включив 8 моментов в моем макете и отправив символ обратно в передатчик.Понимание UART под ATMEGA168A

Вот код, я использую:

//CPU clock 
#define F_CPU 1000000UL 
//Baud 
#define BAUD 9600 
//Baud rate 
#define BAUDRATE ((F_CPU)/(BAUD*16UL)-1) 

#include <avr/io.h> 
#include <util/delay.h> 
#include <util/setbaud.h> 
#include <avr/interrupt.h> 
#include <stdint.h> 

//Communication Parameters: 
//8 bits of data 
//1 bit stop 
//No parity 
void uart_init(void){ 

    //Bit 7 - RXCIEn: RX complete interrupt enable 
    //Bit 6 - TXCIEn: TX complete interrupt enable 
    //Bit 5 - UDRIE: USART data register empty interrupt enable 
    //Bit 4 - RXENn: Receiver enable 
    //Bit 3 - TXENn: Transmitter enable 
    UCSR0B = 0b10011000; 

    //Bit 7 - RXCn: USART receive complete. 
    //Bit 6 - TXCn: USART transmit complete 
    //Bit 5 - UDREn: USART data register empty 
    UCSR0A = 0b00000000; 


    //Bit 11:0 – UBRR11:0: USART baud rate register 
    //Whereas H are the higher bits and L the lower bits 
    //It comes from the setbaud.h 
    UBRR0H = UBRRH_VALUE; 
    UBRR0L = UBRRL_VALUE; 

    //Bit 7:6 - UMSELn1:0: USART mode select 
     //00 Asynchronous USART 
     //01 Synchronous USART 
     //11 Master SPI 
    //Bit 5:3 - Reserved bits in MSPI mode 
    //Bit 2 - UDORDn: Data order 
    //Bit 1 - UCPHAn: Clock phase 
    //Bit 0 - UCPOLn: Clock polarity 
    UCSR0C = 0b10000110; 
} 

// function to send data 
void uart_transmit (uint8_t data) 
{ 
    while (!(UCSR0A & (1<<UDRE0)));   // wait while register is free 
    UDR0 = data;        // load data in the register 
} 

int main (void) 
{ 
    //Starts UART 
    uart_init(); 
    //All led GPIOs as output 
    DDRB = 0xFF; 
    DDRC = 0x01; 
    //Enabling interrupts 
    sei(); 

    while(1) 
    { 
     ; 
    } 

    return 0; 
} 

ISR(USART_RX_vect) 
{ 
    //Variable to hold the incoming char 
    uint8_t received_bit = UDR0; 
    PORTC ^= 0x01; 
    PORTB = 0x00; 
    PORTB = received_bit; 
    uart_transmit(received_bit); 
} 

Когда я прошить на чип и начать использовать его, я получаю странное поведение. Я отправляю «U», который является хорошим двоичным кодом 01010101 для сравнения. Однако я получаю странные ответы назад от моего чипа:

enter image description here

Моими вопросов, касающихся УАПП под ATMEGA168a является следующим:

  • При установке F_CPU я должен остаться с 1MHZ используемый ATMEGA168a, или мне нужно использовать один из моих передатчиков (Intel i7)? Это может быть проблема?
  • Когда UDR0 получает «обновление»? Когда я нажимаю кнопку ввода, чтобы отправить символ на чип через терминал?
  • Что может быть причиной этой проблемы?

ответ

3

В функции uart_init() вы установили биты 7:6 в 10, которая является зарезервированным состояние в соответствии с инструкцией ATMega 168A. Для того, чтобы получить желаемый асинхронный режим работы UART, установите их 00:

UCSR0C = 0b00000110; 

Другой причину, почему ваш пример не работал была настройка скорости пересылки данных, как описано в моем комментарии ниже.

Вы уже включили заголовочный файл <util/setbaud.h>, который содержит макросы, чтобы упростить настройку UART. Посмотрите here для документации. Эти макросы принимают введенные вами данные в F_CPU и BAUDRATE и вычисляют параметры для регистров конфигурации UART (UBRRH_VALUE и UBRRL_VALUE).

Вы использовали почти правильно, однако воспользоваться UART скорости передачи данных особенности ATmega удвоения, добавьте следующий код после установки UBRR0H/значения L:

#if USE_2X 
UCSR0A |= (1 << U2X0); 
#else 
UCSR0A &= ~(1 << U2X0); 
#endif 

Это устанавливает или удаляет U2X0 бит в зависимости от вычислений макросов setbaud.

Кроме того, я полагаю, вы можете удалить строку

#define BAUDRATE ((F_CPU)/(BAUD*16UL)-1) 

, потому что это именно то, что делает setbaud.h.

+0

Не работает. :-( – Bob

+3

Просто заметили другое: вы используете тактовые импульсы процессора 1 МГц и скорость передачи 9600 бит. Согласно таблице 20-4 на стр. 187 [руководства] (http://www.atmel.com/ изображения/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf) это дает вам временную ошибку -7,0%. Это может быть проблемой, поэтому возможно, попробуйте еще одну скорость? –

+0

Спасибо Джо. Если я установил бод на 1200, он отлично работает. Можно ли работать с более высокими значениями бод? – Bob

Смежные вопросы