Попытаемся теперь настроить наш модуль 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
Отладочную плату PIC Open18F4520-16F877A можно приобрести здесь: PIC Open18F4520-16F877A
Семисегментный чертырехразрядный индикатор красный с общим анодом 10 шт
Переходник USB to TTL можно приобрести здесь ftdi ft232rl
Логический анализатор 16 каналов можно приобрести здесь
Смотреть ВИДЕОУРОК (нажмите на картинку)
У вас в функции 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.
можете помочь в решении конкретной задачи или у вас только курсы в интернете