Попытаемся теперь настроить наш модуль USART в режиме приёма данных, и также в данном уроке мы попробуем соединить по шине USART два контроллера.
В прошлом уроке мы изучили, как работает модуль в асинхронном режиме, в том числе в режимах и передачи и приёма данных. Только использовали мы модуль только в режиме передачи данных.
А сегодня мы приступим к режиму приёма данных.
Сначала мы одну из испытуемых плат подключим к ПК и данные на неё мы будем передавать именно с компьютера, а уж затем мы напишем проект для второго контроллера и соединим их вместе и посмотрим, что у нас из этого получится.
В качестве первой платы мы возьмём макетную плату с контроллером PIC16F876A.
Первым делом мы вернём контакт четвёртого разряда индикатора обратно с ножки RC7 на ножку RC3 контроллера
Подключим переходник USB-TTL к соответствующим ножкам контроллера
Также подключим программатор и соединим его, а также переходник, с ПК
Перейдём к проекту.
Проект сделан из проекта урока 22 с именем I2C_MASTER и назван USART_TXRX1.
Откроем наш проект в MPLAB X и сделаем его главным.
В файле led.c исправим RC7 на RC3
здесь
1 2 3 |
if(n_count==0) { PORTCbits.RC3 = 0; |
и здесь
1 2 |
segchar(R4); PORTCbits.RC3 = 1; |
Перейдём в файл main.c, подключим библиотеку для работы со строками, а также добавим две глобальные переменные, которые нам пригодятся чуть позже
1 2 3 4 5 |
#include "main.h" #include "string.h" //-------------------------------------------------------------- unsigned char bt, tmp; //-------------------------------------------------------------- |
Функцию обработчика прерываний от таймера преобразуем вот в такой вид, так как нам будет надо обрабатывать ещё одно прерывание
1 2 3 4 5 6 7 8 |
void interrupt isr(void) { if(TMR0IE&&TMR0IF) { TIM0_Callback(); T0IF=0; } } |
Остальные функции, кроме main(), удалим вместе с телами.
В функции main() сначала удалим вторую локальную переменную
unsigned int i, n;
После строки «TMR0=0;» удалим весь код до бесконечного цикла.
В бесконечном цикле оставим цикл for с задержкой, остальное удалим, после чего цикл примет следующий вид
1 2 3 4 5 6 7 |
while(1) { for(i=1;i<256;i++) { __delay_ms(100); } } |
Настроим направление ножек порта RC
1 2 |
TMR0=0; TRISC=0xC0;//RC and RC Input (USART (TX) and USART (RX)) |
Настроим скорость USART
1 2 |
TRISC=0xC0;//RC and RC Input (USART (TX) and USART (RX)) SPBRG=12; //19200 |
Настроим USART на передачу и включим его так же, как и в прошлом занятии
1 2 3 4 5 6 7 |
SPBRG=12; //19200 TX9 = 0; TXEN = 1; SYNC = 0; BRGH = 1; TX9D = 0; SPEN = 1; |
Выше функции main() добавим также все функции которые мы писали для работы с USART в прошлом уроке
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
//-------------------------------------------- void USART_Transmit(unsigned char tx_byte) { while(!TRMT) ; TXREG=tx_byte; } //------------------------------------------------ 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++; } } //------------------------------------------------ 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++; } } //------------------------------------------------ |
Затем передадим число в бесконечном цикле функции main()
1 2 3 |
for(i=1;i<256;i++) { USART_Transmit(i); |
Соберём код, прошьём контроллер, запустим терминальную программу, настроим скорость там также 19200 и включим режим отображения Hex, нажмём Connect и посмотрим результат
Всё отлично передаётся.
Теперь нам надо попробовать что-то принять. Можно это проделать с помощью скрипта в терминальной программе и написать там код для передачи нашему контроллеру, а затем в нём всё это попробовать принять. Надеюсь, те, кто следят за моими уроками по другим контроллерам, уже знают, как пишутся скрипты в терминальной программе, и вопросов не возникнет. Поэтому нажмём в ней кнопку Scripting и напишем скрипт вот такого содержания
1 2 3 4 5 6 7 8 9 10 11 12 |
program test; var j: byte; begin while (true) do begin for j:=0 to 255 do begin ComSendchr(j); Delay(100); end; end; end. |
Сохраним его под каким-нибудь именем и пока запускать не будем. У нас ещё нет кода для приёма, поэтому вернёмся в наш проект.
Передачу в USART пока закомментируем, так как контроллер-то прекрасно умеет передавать и принимать данные одновременно, а вот терминальная программа порой нет
1 |
//USART_Transmit(i); |
В функции main() настроим также приём данных
1 2 3 4 5 6 7 8 |
TX9D = 0; RX9 = 0; CREN = 1; RX9D = 0; RCIE=1; GIE=1; PEIE=1; SPEN = 1; |
Мы запретили 9-битный приём, включили приёмник, включили от него прерывания, а также разрешили глобальные прерывания
Добавим ветку в обработчик прерываний для обработки прерываний от модуля USART
1 2 3 4 5 |
T0IF=0; } if(RCIF) { } |
В теле условия обработки прерывания обработаем условие ошибки кадра. В этом случае мы просто освободим регистр с помощью считывания, затем покинем обработчик
1 2 3 4 5 6 7 8 |
if(RCIF) { if(FERR) { tmp = RCREG; return; } } |
Далее аналогичным образом обработаем также переполнение внутреннего буфера, только мы уже считывать регистр не будем, а перезагрузим бит
1 2 3 4 5 6 7 8 |
return; } else if (OERR) { CREN = 0; CREN = 1; return; } |
Ну и, если мы не встретились с ошибками и не покинули наш обработчик, то примем байт из буфера, затем отобразив его на индикаторе
1 2 3 4 |
return; } bt=RCREG; ledprint(bt); |
Соберём код, прошьём контроллер, запустим обмен в терминальной программе, а затем запустим там наш скрипт кнопкой Run в нём. Если всё нормально, то наш индикатор начнёт считать
В следующей части занятия мы соединим две платы с контроллерами по USART, напишем проект для второго устройства и проверим работу USART в полнодуплексном режиме.
Предыдущий урок Программирование МК PIC Следующая часть
Купить программатор (неоригинальный) можно здесь: PICKit3
Купить программатор (оригинальный) можно здесь: PICKit3 original
Семисегментный чертырехразрядный индикатор красный (с общим анодом или катодом на выбор) 10 шт
Переходник USB to TTL можно приобрести здесь ftdi ft232rl
Логический анализатор 16 каналов можно приобрести здесь
Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)
У вас в функции USART_Transmit ошибка. После оператора while не стоят скобки, он полностью игнорируется.
Всё будет работать и ничего не игнорируется. обычное окончание строки превратится в NOP и будет вертеться в цикле. Это все равно что поставить открывающую и закрывающую фигурные скобки, тогда точка с запятой будет не нужна.
А Вы в дизассемблере проверяли?
Если бы игнорировалось, то повисло бы всё.
Только что в кейле на STM проверил
присвоил переменной i значение 9
после этого применил вот такой цикл
while(i) ;
Он конечно скорее всего получится бесконечный, так как вряд ли кто-то где-то присвоит нашей переменной нулевое значение, хотя можно в обработчике прерываний либо в другой задаче если у нас OS
А интерпретатор превратил нашу строку вот в такие вот три строки
0x08001DE0 BF00 NOP
0x08001DE2 2C00 CMP r4,#0x00
0x08001DE4 D1FD BNE 0x08001DE2
То есть мы будем переходить на адрес 0x08001DE2 до тех пор, пока значение в регистре r4 не станет равным нулю.
Попробуем теперь вот так
while(i) {}
Получим абсолютно то же самое.
Поэтому, скорее всего, у Вас компилятор какой-то странный.
после считывания в rx остается один байт Как очистить буфер rx.
можете помочь в решении конкретной задачи или у вас только курсы в интернете