§ 41. USART. Пример практической реализации.
|
Киселев Роман, Июнь 2007
|
Статья обновлена 26 Мая 2014
|
|
В этой статье попробуем собрать простое устройство на МК, которое будет принимать байт информации через COM-порт
и немедленно выводить его на семисегментном индикаторе, а также отправлять подтверждение о доставке обратно в компьютер.
|
Если Вы читали предыдущую статью (надеюсь на это), то, наверное, заметили, что рабочие напряжения в COM-порту +12 В и -12 В,
а МК оперирует напряжениями +5 В и 0 В. Для того, чтобы все работало нормально, нужно установить преобразователь уровней.
Рекомендую ставить MAX232. Потребуются, помимо микросхемы, 5 конденсаторов на 1 мкФ.

При работе с COM-портом именно эта микросхема находит наиболее частое применение. Если Вы купили макетную плату с разводкой
под СОМ-порт, то там, скорее всего, будет и готовая разводка под установку MAX232 и конденсаторов. Правда, когда я купил
свою плату, то сначала припаял МК и цепь питания, потом СОМ-порт. Долго не мог понять, как крепить преобразователь уровня.
И тут вдруг выяснилось, что все компоненты я припаял не с той стороны к плате :-). Но не переделывать же все!
Поэтому я прицепил СОМ-порт и МАХ232 к "правильной" стороне, а остальное оставил на "неправильной".
У меня в схеме задействованы выводы 11 (T1in) и 12 (R1out). Соответственно, вывод 13 (R1in)
подключен к 3-му выводу розетки СОМ-порта (RXD), а 14-й вывод МАХ-232 (T1out) подсоединен ко 2-му выводу розетки
СОМ-порта (TXD).
Теперь нужно МАХ232 подсоединить к МК. У ATMEGA16 USART использует 14-й вывод PB0 (RXD) для приема данных и PB1 (TXD) для
отправки. Соответственно, PB0 нужно прикрепить к 12-му выводу МАХ232, а PB1 к 11-му. Ну и все. Не забудьте только соединить
"земли" МК, МАХ232 и СОМ-порта между собой! :-)
Остается лишь написать программу для МК (для ПК тоже можно). В данном примере реализована работа с кварцем 11,0592 МГц, битрейт 115,2 кбит/с,
8 информационных бит, нет бита четности, 1 стоп-бит, скорость удвоенная. С большим, чем 115,2 кбит/с битрейтом мой компьютер работает с глюками.
Ниже приведен код программы для МК.
#include "iom16.h"
#define a 1
#define b 4
#define c 16
#define d 64 // Это для индикатора
#define e 128
#define f 2
#define g 8
#define DP 32
unsigned char Dig[10];
// В этих переменных хранятся цифры, которые нужно отобразить
char Disp5, Disp6, Disp7;
// Функция выделяет цифры из трехзначного числа Number
void Display (unsigned char Number)
{
unsigned char Num1, Num2, Num3;
Num1=Num2=0;
while (Number >= 100)
{
Number -= 100;
Num1++;
}
while (Number >= 10)
{
Number -= 10;
Num2++;
}
Num3 = Number;
Disp5 = Dig[Num1];
Disp6 = Dig[Num2];
Disp7 = Dig[Num3];
}
void USART_init()
{
UCSRA = (1 << 1); // Установка двойной скорости
UCSRB |= (1 << 7) | (1 << 4) | (1 << 3); // Прерывание по приему данных, включены приемник и передатчик
UCSRC |= (1 << 7); // Запись в UCSRC
UCSRC |= (1 << 1) | (1 << 2); // Размер кадра данных 8 бит
UCSRC -= 128; // Запись в UBRRH
UBRRH = 0;
UBRRL = 11; // Битрейт равет 115200 бит в секунду
}
void Dig_init()
{
Dig[0] = (a+b+c+d+e+f);
Dig[1] = (b+c);
Dig[2] = (a+b+g+e+d);
Dig[3] = (a+b+g+c+d);
Dig[4] = (f+g+b+c);
Dig[5] = (a+f+g+c+d);
Dig[6] = (a+f+g+c+d+e);
Dig[7] = (a+b+c);
Dig[8] = (a+b+c+d+e+f+g);
Dig[9] = (a+b+c+d+f+g);
}
void io_init() // Инициализация портов ввода/вывода
{
DDRA = 0xFF;
PORTA = 0;
DDRC |= (1 << PINC5) | (1 << PINC6) |(1 << PINC7);
PORTC = 0;
DDRB = 1;
}
void main()
{
unsigned char j, k = 0;
USART_init();
Dig_init();
Display(0);
SREG |= (1 << 7);
io_init();
while(1) // Отображение принятого байта
{
for (j = 0; j <= 50; j++){} // Задержка для отображения цифры
(k == 3) ? k = 0 : k++;
PORTC &= 31; //Очистка PC7, PC6, PC5
for (j = 0; j<=30; j++){} // Задержка для выключения транзистора
switch (k)
{
case 0: PORTC |= (1 << PINC7); // Единицы
PORTA = Disp7;
break;
case 1: PORTC |= (1 << PINC6); // Десятки
PORTA = Disp6;
break;
case 2: PORTC |= (1 << PINC5); // Сотни
PORTA = Disp5;
}
}
}
#pragma vector = USART_RXC_vect
__interrupt void Recieve()
{
unsigned char temp = 0;
unsigned char* str = " Hello! My name is AtMega16! "; // Строка данных
char t,l;
temp = UDR; // Чтение принятых данных
Display (temp); // Отображение числа на индикаторе
PORTB = 1 - PORTB; // Зажигаем/гасим светодиод на PB0
if (temp == 5) // Отправка строки, если принятый байт равен 5
{
for (t=0; t < 28; t++)
{
UDR = str[t]; // Отправка строки
for (l=0; l < 200; l++) // Задержка (чтобы успел отправить число)
{ }
}
}
else
UDR = temp; // Отправка обратно принятого числа
}
Теперь нужно позаботиться о программе в компьютере, которая будет управлять СОМ-портом и работать с МК.
Можно просто взять готовую программу из статей о СОМ-порте компьютера, основанную на библиотеке SerialGate.dll. Скачать данный софт как и программу Termonal.exe (о ней далее) можно в файлах к данной статье.
Запускаем программу, подключаем наше устройство к СОМ-порту, подаем питание на него, в программе выбираем СОМ-порт
и устанавливаем битрейт 115200 бит/с. Давайте отправим какой-нибудь символ, например, "&". МК отправит его обратно
и отобразит на индикаторе его номер - 38. Отправив строку, получаем ее обратно. Заметьте, что при нечетном количестве
символов меняется состояние светодиода, подключенного к PB0. При каждом прерывании он загорается либо гаснет.

Теперь давайте рассмотрим другую программу из этого архива - Terminal.exe. Не знаю, кто ее автор, но ему СПАСИБО!
Это очень мощная и удобная программа, позволяющая делать с СОМ-портом практически все, что угодно.
Запустив программу, выберите номер порта, битрейт 115200, 8 битов данных, четность "none", 1 стоп бит.
Нажимаем Connect и можем теперь отправлять данные МК. Символы передаются так же, как и в предыдущей программе, в виде их
ASCII - значений, но если набрать "#xxx", где ххх-трехзначное число до 255, то можно передать любой символ, в т.ч. и непечатный.
Если МК получает символ с номером 5, то он вместо него обратно отсылает строку " Hello! My name is AtMega16! ". 13-й символ - это
переход на след. строчку. Кстати, ASCII таблица в программе тоже есть.

© Киселев Роман
Июнь 2007
http://www.kernelchip.ru