Урок 14
Часть 3
USART. Связь МК с ПК
Сегодня мы продолжим изучение программирования интерфейса USART.
В предыдущей части занятия мы закончили обзор регистров данного интерфейса и создали проект в Atmel Studio. Тепtрь мы продолжим работать с данным проектом.
Ну и как обычно водится, для любого интерфейса или датчика, мы сначала напишем функцию его иницbализации. Создадим её каркас в файле usart.c. Возвращать данная функция нам ничего не будет, а передавать мы ей будем значение UBRR для того, чтобы задать скорость приема-передачи данных
void USART_Init( unsigned int speed)//Инициализация модуля USART
{
}
И, так как регистровая пара UBRR у нас 16-битная и представляет собой два регистра, то, соответственно мы по ним и распределим наше число. Старшую часть мы отправим в UBRRH, а младшую — в UBRRL. Делается это с помощью битового сдвига
void USART_Init( unsigned int speed)//Инициализация модуля USART
{
UBRRH = (unsigned char)(speed>>8);
UBRRL = (unsigned char)speed;
Тут сразу может возникнуть вопрос. Мы, наверно, помним, а может кто забыл, что самый старший бит в регистре UBRRH, называемый URSEL, отвечает за переключение регистров, а мы его никак не используем. Ответ такой. Мы не будем передавать в регистровую пару не слишком большие величины, поэтому даннвй регистр останется в нуле, а пока он в нуле, то обращение идёт именно к регистру UBRR. Поэтому ничего страшного.
Далее включим определённые биты в управляющих регистрах шины
UBRRL = (unsigned char)speed;
UCSRB=(1<<RXEN)|( 1<<TXEN); //Включаем прием и передачу по USART
UCSRB |= (1<<RXCIE); //Разрешаем прерывание при передаче
UCSRA |= (1<<U2X); // Для 8 мгц
UCSRC = (1<<URSEL)|(1<<USBS)|(1<<UCSZ1)|(1<<UCSZ0);// Обращаемся именно к регистру UCSRC (URSEL=1),
//ассинхронный режим (UMSEL=0), без контроля четности (UPM1=0 и UPM0=0),
//1 стоп-бит (USBS=0), 8-бит посылка (UCSZ1=1 и UCSZ0=1)
//UCSRC |= (1<<UPM1);//четность
}
Теперь по порядку разберёмся, что мы с вами тут включили.
В регистре UCSRB мы включим следующие биты
Биты RXEN и TXEN включают USART соответственно на прием и передачу. Так как мы будем пользоваться обоими направлениями, мы их оба и включим.
Бит RXCIE разрешает прерывания по приемной шине. Без прерываний на приём работать практически невозможно. Нам придётся тогда как-то угадывать, когда к нам придут данные, а с прерываниями всё гораздо проще. Обработчик нам даст понять. когда именно данные придут именно в тот момент, когда данные будут в регистре, то есть приём будет закончен.
Следующий регистр — UCSRB. В нём включим только один бит, отвечающий за удвоение скорости. Данный бит мы с вами уже подробно разобрали в предыдущих частях урока
Теперь последнbй управляющий регистр — UCSRC, в котором мы включим следующие биты
В принципе биты данного регистра мы все разобрали в прошлом уроке, поэтому говорить о них лишний раз нет необходимости. Тем не менее вдобавок всё объяснено в коде в комментариях.
Вот, собственно, и вся инициализация интерфейса USART. А уже работать с данной функцией мы будем в следующей части занятия.
Предыдущая часть Программирование МК AVR Следующая часть
Программатор и переходник USB-TTL можно приобрести здесь:
Программатор USBASP USBISP с адаптером USBASP USBISP 3.3 с адаптером
Переходник USB-TTL лучше купить такой (сейчас у меня именно такой и он мне больше нравится)
Смотреть ВИДЕОУРОК в КuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)
Добрый вечер!
Скажите пожалуйста как работает данная конструкция?
void USART_Init( unsigned int speed)//Инициализация модуля USART
{
UBRRH = (unsigned char)(speed>>8);
UBRRL = (unsigned char)speed;
я понимаю что мы делаем(присваиваем регистру значение)
Зачем нужно добавлять unsigned char? Почему нельзя просто делать маски и сдвигать?
С уважением Осеков С.С.
Вам, вероятно, нужно сначала почитать вообще про язык СИ, и у Вас такие вопросы отпадут.
Но всё равно осмелюсь ответить.
Тип переменной в скобках перед операном — это называется явное преобразование.
Применяется когда переменная для присваивания результата операции и один из операндов имеют разный тип.
У нас speed — это переменная шестнадцатибитная беззнаковая целочисленная, а регистровая пара UBRR состоит из регистров UBRRH и UBRRL, которые являются 8-битными. Так вот чтобы преобразовать к тому же типу и отрезать старшую часть от операнда, мы и применяем явное преобразование типов.
Скорее всего и без того будет работать и всё отрежется, но это уже называется неявное преобразование типа.
Но предсказуемость этого далеко не точная.
Спасибо !
Наконец я разобрался с этими строками:
void USART_Init( unsigned int speed)
//здесь мы объявляем переменную speed типа int 16 бит
{
UBRRH = (unsigned char)(speed>>8);//а зесь преобразуем тип
//этой переменной в тип char 8 бит
UBRRL = (unsigned char)speed;//аналогично
/*если какое-то значение нужно привести к другому типу, нужно перед этим значением в скобках написать название требуемого типа.это и есть явное преобразование */
UBRRH = (uint16_t)(speed>>8);
так намного понятней сразу видно что оно 16-разрядное, мне кажется
Здравствуйте, подскажите, пожалуйста, запись UCSRC = (1<<USBS) разве не означает присвоение 1 биту USBS, и это 2 стоповых бита? а в комментариях написано, что USBS=0 и это 1 стоп-бит.
Ошибся, наверно. Посмотрите по даташиту к контроллеру.
И еще небольшая опечатка
Там где в регистр UCSRA Пишем U2X. У вас там написано:
Следующий регистр — UCSRB, а мы уже пишем в регистр UCSRA
Добрый день:
UCSRB |= (1<<RXCIE); //Разрешаем прерывание при передаче
Наверно имелось ввиду "Разрешение прерывания по завершению приема "?