usart - передача данных по последовательному порту USART

В примере usart демонстрируется использование нескольких классов:

  • Класс, реализующий функции 16-битного таймера-счётчика 1, используется для отсчёта времени задержки мигающего светодиода (как в примере timer).
  • Вспомогательный класс потенциометра Pot (файл misc/pot.h) используется для управления временем задержки мигающего светодиода.
  • Класс, реализующий функции 8-битного таймера-счётчика 0, используется для отсчёта интервалов между передачами показаний потенциометра по последовательному порту USART.
  • Класс, реализующий функции интерфейса последовательного порта USART, используется для передачи показаний потенциометра.

Данные передаются как шестнадцатиричные числа в строковом режиме (одно число на строку).

Исходный код примера:

/** 
 * usart.cpp 
 * 
 *  VE_AVR_Library ADC Control LED Blinking Example. 
 * 
 *  Created on: 11.05.2012 
 *  Author: andrey 
 */ 
#include <ve_avr.h> 
#include <misc/ve_led.h> 
#include <misc/ve_pot.h>  

#define LED              DEV_GPIOB, 7       // Светодиод LED подключен к выводу PB7 микроконтроллера 
#define LED_POT_CHANNEL  AnalogMux::CH_ADC0 // Потенциометр LED_POT_CHANNEL подключен к выводу ADC0
                                            // микроконтроллера  
volatile bool bLedOn = false;        // Флаг состояния светодиода LED (false - выключен) 
volatile uint16_t potValue;          // Состояние потенциометра, умноженное на 64 
volatile uint8_t bSendPotValue = 16; // Счётчик отправки сообщений от состоянии потенциометра по USART  
char hexChar(uint8_t hex);           // Функция перевода числа [0..15] в шестнадцатеричный формат  

int main() 
{
   DEV_POWER.adcOn();                // Включить питание АЦП
   DEV_POWER.timer1On();             // Включить питание таймера-счётчика 1
   DEV_POWER.usart0On();             // Включить питание USART 0

   led::setup(LED);                  // Предварительная настройка вывода светодиода LED

   Pot pot;
   pot.setup(LED_POT_CHANNEL);       // Предварительная настройка канала АЦП LED_POT_CHANNEL
   potValue = pot.getValue() << 6;   // Первый опрос потенциометра

   // Предварительная настройка таймера-счётчика 1
   DEV_TIMER1.setClockSelect(TimerW::Prescaler_64);  // Частота равна CLKIO/64 (например 16 МГц / 64 = 250 кГц)
   DEV_TIMER1.setWaveGenMode(TimerW::FastPWM_OCRA);  // Режим быстрого ШИМ со сравнением TCNT1 == OCR1A
   DEV_TICTRL1.outCompIntEnableA();                  // Разрешить прерывание сравнения (TIMER1_COMPA_vect)

   // Предварительная настройка таймера-счётчика 0
   DEV_TIMER0.setClockSelect(Prescaler0::Prescaler_1024); // Частота равна CLKIO/1024 
                                                          // (например 16 МГц / 1024 = 15625 Гц)
   DEV_TIMER0.setWaveGenMode(Timer0::Normal);             // Режим простого счёта
   DEV_TICTRL0.overflowIntEnable();                       // Разрешить прерывание по переполнению
                                                          // (TIMER0_OVF_vect)

   DEV_USART0.setBaudRate(57600);     // Скорость передачи данных 57600 бод (формат по умолчанию 8N1)
   DEV_USART0.transmitterEnable();    // Разрешить передачу данных

   enableInterrupts();                // Разрешить прерывания

   while(true) {
      potValue = pot.getValue() << 6;    // Опрос потенциометра
      if (bLedOn)                        // Если светодиод LED должен светиться
         led::on(LED);                   // включить светодиод LED
      else                               // и наоборот
         led::off(LED);
      if (bSendPotValue == 0) {          // Если пора отправить данные по USART
         DEV_USART0 << hexChar(potValue >> 12); // отправить состояние потенциометра, умноженное на 64
         DEV_USART0 << hexChar(potValue >> 8);  // в шестнадцатеричном формате
         DEV_USART0 << hexChar(potValue >> 4);
         DEV_USART0 << hexChar(potValue);
         DEV_USART0 << "\r\n";                  // Одно данное на строку
         bSendPotValue = 16;                    // Обновить счётчик отправки сообщений
      }
   } 
}  

ISR(TIMER1_COMPA_vect)                      // Обработчик прерывания сравнения таймера-счётчика 1 
{
   DEV_TIMER1.setOutputCompareA(potValue);  // Установить интервал времени до следующего прерывания
   bLedOn = ! bLedOn;                       // Переключить состояние светодиода LED через флаг состояния 
}  

ISR(TIMER0_OVF_vect)           // Обработчик прерывания переполнения таймера-счётчика 0 
{
   if (bSendPotValue > 0)      // Уменьшить текущее значение счётчика отправки сообщений на единицу
      --bSendPotValue;         // т.о. при частоте CLKIO = 16 МГц сообщения будут отправляться
                               // с частотой (15624 Гц / 256) / 16 = 3 Гц 
}  

char hexChar(uint8_t hex)      // Функция перевода числа [0..15] в шестнадцатеричный формат 
{
   char ret = (hex & 0x0F);
   return (ret <= 9) ? (ret + '0') : (ret + 'A'- 10); 
} 

Предыдущий пример: timer - прерывания от таймера.

Следующий пример: EEPROM - чтение и запись данных в память EEPROM.

Скачать библиотеку VE_AVR.

Автор: Андрей Шаройко <vanyamboe@gmail.com>