В предыдущей части урока мы познакомились с шиной USART, в том числе с организацией шины в контроллере PIC16 и подключили нашу практическую схему.
Проект мы сделаем из проекта прошлого урока для ведомого устройства I2C под названием I2C_SLAVE и назовём его USART_TX.
Питать плату мы будем от программатора.
Откроем наш проект в MPLAB X, сделаем его главным, зайдём в настройки и убедимся, что контроллер будет питаться от программатора.
Удалим в файле main.c глобальные переменные
unsigned char bt=0;
unsigned char j;
Затем удалим обработчик прерывания вместе с телом, а также из функции main() удалим всё, оставив только пустой бесконечный цикл. Данная функция примет вот такой вид
1 2 3 4 5 6 |
void main() { while(1) { } } |
Добавим в данной функции строковый массив, переменную для счётчика и настроим на вход наши ножки TX и RX
1 2 3 4 5 6 |
void main() { char str1[15]; int i; TRISC6 = 1; //USART (TX); TRISC7 = 1; //USART (RX); |
Согласно таблице в даташите, настроим скорость передачи данных в 19200 бит в секунду
1 2 |
TRISC7 = 1; //USART (RX); SPBRG=12; //19200 |
Настроим биты, необходимые для использования режима передачи
1 2 3 4 5 6 7 |
SPBRG=12; //19200 TX9 = 0; TXEN = 1; SYNC = 0; BRGH = 1; TX9D = 0; SPEN = 1; |
В бесконечный цикл вставим цикл. в котором попробуем передать по шине инкрементирующееся число от 1 до 255
1 2 3 4 5 6 7 8 |
while(1) { for(i=0;i<256;i++) { TXREG=i; __delay_ms(105); } } |
Включим терминальную программу, настроим её на скорость 19200, а также отображение включим шестнадцатеричное
Соберём проект, прошьём контроллер и нажмём в терминальной программе кнопку Connect.
Если всё правильно, то мы увидим вот такой результат
Теперь давайте запустим программу логического анализа и настроим наш USART там.
Включим только один канал, так как приёмом мы сегодня не занимаемся
Добавим анализатор Acync Serial и настроим его следующим образом
Сохраним настройки и нажмём кнопку START.
Рассмотрим передачу отдельно взятого байта
Сначала мы видим переход из высокого состояния в низкое, что соответствует стартовому биту, после стартового бита идут три единицы, а затем пять нулей, что и соответствует цифре 7 (не забываем, что данные у нас идут от младших битов к старшим). А затем шина уходит в высокое состояние, что соответствует стоповому биту.
В случае, если старший бит в байте будет в единице, то у нас шина просто остаётся в высоком состоянии, что также соответствует биту СТОП
Посмотрим также, что байты наши не пропускаются, они передаются все
Мы применяли задержку, но если бы мы передавали байты без задержки, то у нас бы были обязательно пропуски, так как при передаче необходимо проверять, что предыдущая передача закончилась и шина у нас свободна. Поэтому для передачи мы будем использовать функцию, которую мы сами напишем и добавим её над функцией main()
1 2 3 4 5 6 7 |
//------------------------------------------------ void USART_Transmit(unsigned char tx_byte) { while(!TRMT) ; TXREG=tx_byte; } //------------------------------------------------ |
Вот теперь у нас будет всё нормально, поэтому в функции main() в бесконечном цикле изменим обычное присвоение регистру значения вызовом нашей функции
1 |
USART_Transmit(i); |
Проверим, что у нас по-прежнему всё работает.
Теперь для того, чтобы убедиться, что у нас всё отслеживается, мы попробуем передавать сразу по несколько байт, так как передавать всё по одному байту — это хорошо, но зачастую бывают ситуации, когда нам требуется передать сразу какую-то последовательность байтов или буфер, например, строку.
Давайте напишем для удобства функцию, которая будет этим заниматься. Добавим её над функцией main()
1 2 3 4 5 6 7 8 9 10 11 |
//------------------------------------------------ void USART_Transmit_Arr(unsigned char *tx_buff, unsigned int tx_len) { unsigned int cnt=0; while(cnt<tx_len) { USART_Transmit(tx_buff[cnt]); cnt++; } } //------------------------------------------------ |
В качестве входных параметров мы передаём указатель на наш массив с данными, а также длину передаваемых данных.
А в теле функции мы отслеживаем то, что у нас байт ещё не последний в нашем массиве, передаём его в шину.
Перейдём в наш цикл в функцию main(), закомментируем передачу байта и попробуем с помощью нашей новой функции передать строку
1 2 3 4 |
for(i=0;i<256;i++) { //USART_Transmit(i); USART_Transmit_Arr("1234567890\r\n",12); |
Соберём код, прошьём контроллер и посмотрим результат в терминальной программе, для чего сначала переключим режим отображения данных
Теперь нажмём кнопку Connect и посмотрим результат выполнения программы
Всё отлично приходит в терминальную программу.
Посмотрим также в логическом анализе, что между отправленными байтами у нас практически нет промежутков, что они следуют друг за другом практически непрерывно
Промежутков нет вообще, за битом СТОП тут же следует бит СТАРТ. То есть, на один байт уходит 10 бит передачи. Поэтому, чтобы нам определить реальную скорость передачи в байтах в секунду, то нам надо будет 19200 разделить не на 8, а на 10, и мы получим 1920 байт в секунду.
Порой приходится передавать длинные строки, которые заканчиваются нулём. И в этом случае нет смысла считать байты в строке, достаточно лишь отследить ноль.
Подключим в main.c библиотеку для работы со строками
1 2 |
#include "main.h" #include "string.h" |
А теперь напишем ещё одну функцию, которая уже будет его проверять и во входном параметре в ней достаточно будет лишь указателя на массив со строкой
1 2 3 4 5 6 7 8 9 10 11 12 |
//------------------------------------------------ void USART_Transmit_Str(char *str_buff) { unsigned int cnt=0; unsigned int tx_len = strlen(str_buff); while(cnt<tx_len) { USART_Transmit(str_buff[cnt]); cnt++; } } //------------------------------------------------ |
Испытаем данную функцию также в бесконечном цикле
1 2 |
//USART_Transmit_Arr("1234567890\r\n",12); USART_Transmit_Str("1234567890\r\n"); |
Можете проверить данный код, всё будет также правильно работать.
Также попробуем передать различные строки, для этого нам поможет функция стандартной строковой библиотеки sprintf
1 2 3 |
//USART_Transmit_Str("1234567890\r\n"); sprintf(str1,"String%03d\r\n",i); USART_Transmit_Str(str1); |
Проверим результат
Все строки прекрасно приходят в терминальную программу, байты по-прежнему идут непрерывно
Попробуем немного увеличить скорость, выставив другое значение в SPBRG
SPBRG=3;
Представим, что у нас нет никаких таблиц и мы вообще не умеем рассчитывать скорость.
Для этого соберём проект прошьём контроллер и настроим наш анализатор следующим образом
Мы установили битрейт, заведомо больший, чем ожидается. А также, самое главное, установили чекбокс, который включит автоопределение битрейта.
Сохраним настройки, нажмём START
У нас по-прежнему всё прекрасно передаётся, правда, пропуски между байтами теперь стали побольше, ну ничего, для такой скорости это нормально.
А теперь опять зайдём в настройки анализатора, и увидим, что скорость, которая определилась, у нас уже там установлена
Теперь идём в терминальную программу и, так как стандартных скоростей таких не бывает, выставим скорость вручную
Жмём Connect и у нас снова всё будет прекрасно приходить в окно терминала.
Таким образом, сегодняшний урок нас научил пользоваться режимом USART в контроллере PIC с помощью одноимённого модуля. Также с помощью переходника USB-TTL нам удалось передать данные с контроллера на ПК, что позволило обеспечить между ними связь.
Всем спасибо за внимание!
Предыдущая часть Программирование МК PIC Следующий урок
Купить программатор (неоригинальный) можно здесь: PICKit3
Купить программатор (оригинальный) можно здесь: PICKit3 original
Переходник USB to TTL можно приобрести здесь ftdi ft232rl
Логический анализатор 16 каналов можно приобрести здесь
Смотреть ВИДЕОУРОК (нажмите на картинку)
Добавить комментарий