|
PIC 16F84. Последовательная передача через порт |
|
|
|
Jul 16 2011, 19:13
|
Группа: Новичок
Сообщений: 4
Регистрация: 16-07-11
Пользователь №: 66 258

|
Вообщем задумал я организовать дистанционное управление на оптопаре, но сначала решил всё проверить на компе и как всегда это бывает ничего у меня не получилось)) Код для передатчика: Код #include <16f84.h> #use delay(clock=4000000) #fuses XT,NOWDT #byte PORTB = 0x06 #byte TRISB = 0x086 #byte PORTA = 0x05 #byte TRISA = 0x085 #byte INTCON = 0x0B #byte OPTION_REG = 0x081 #bit T0CS = OPTION_REG.5 #bit PS0 = OPTION_REG.0 #bit PS1 = OPTION_REG.1 #bit PS2 = OPTION_REG.2 #bit GIE = INTCON.7 #bit T0IE = INTCON.5 #bit T0IF = INTCON.2 void main () { PORTA=0; TRISA=0b1111; PORTB=0b00000001; TRISB=0; while (1) { if (PORTA==0b0001) { PORTA=0; PORTB=0b10000001; T0CS=0; PS0=1; PS1=1; PS2=1; T0IE=1; GIE=1; while (T0IF!=1) { PORTB=0b00000001; } T0IF=0; while (T0IF!=1) { PORTB=0b00000001; } T0IF=0; while (T0IF!=1) { PORTB=0b00000001; } T0IF=0; while (T0IF!=1) { PORTB=0b10000001; } T0IF=0; T0IE=0; GIE=0; } } } Код для приёмника: Код #include <16f84.h> #use delay(clock=4000000) #fuses XT,NOWDT #byte PORTB = 0x06 #byte TRISB = 0x086 #byte INTCON = 0x0B #byte OPTION_REG = 0x081 #bit GIE = INTCON.7 #bit T0IF = INTCON.2 #bit T0IE = INTCON.5 #bit T0CS = OPTION_REG.5 #bit PS0 = OPTION_REG.0 #bit PS1 = OPTION_REG.1 #bit PS2 = OPTION_REG.2 int8 result=0b00000000; void main() { TRISB=0b00000001; PS0=1; PS1=1; PS2=1; T0CS=0; PORTB=0; while(1) { if (PORTB==0b00000001) { T0IE=1; GIE=1; PORTB=0; while (T0IF!=1) { if (PORTB==0b00000000) result=0; } T0IF=0; while (T0IF!=1) { if (PORTB==0b00000000) result=0; } T0IF=0; while (T0IF!=1) { if (PORTB==0b00000000) result=0; else result=result | 0b00000010; } T0IF=0; while (T0IF!=1) { if (PORTB==0b00000000) result=0; else result=result | 0b00000001; } T0IF=0; T0IE=0; GIE=0; } if (result==0b00000001) PORTB=0b10000000; } } Идея в том, что по нажатию кнопки выполняется какое то действие. Для примера я сделал, чтобы загорался светодиод...только ничего не происходит Вот грубая схемка этого чудо устройства
Эскизы прикрепленных изображений
|
|
|
|
|
 |
Ответов
(1 - 6)
|
Jul 16 2011, 21:14
|
Группа: Новичок
Сообщений: 4
Регистрация: 16-07-11
Пользователь №: 66 258

|
Так не получается ничего....не работает моя прошивка..может подскажите что в ней не так?
|
|
|
|
|
Jul 16 2011, 21:55
|
Группа: Новичок
Сообщений: 4
Регистрация: 16-07-11
Пользователь №: 66 258

|
Получается, что я как бы свой протокол написал..только нерабочий)) ВСё это работает очень просто. Нажав кнопку, я инициализирую процесс передачи, который заключается в следующем: сначала передаётся старт бит, равный 1, потом включается таймер и пока он не будет сброшен (это примерно 0,06секунды) передается следующий бит..и т.д. В моём случае я передаю всего полбайта, что соответсвует номеру нажатой кнопки (1,2,3 и т.д...на схеме представлена только одна для простоты описания). Чтобы начать считывать приёмник ждёт старт бита 1. Получив его, он также в течении 0,06 секунды считывает состояние на входящей ножке и записывает результат в переменную. По идеи всё должно работать, но не работает...может код корявый?))Теория то впринципе верна..
|
|
|
|
|
Jul 17 2011, 12:01
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(FOX_ @ Jul 17 2011, 01:55)  По идеи всё должно работать, но не работает...может код корявый?))Теория то впринципе верна.. Увы, проги работают не за идею или теорию, а в соответствии с понаписатым. Подобные ошибки обсасывались стотыщьпицот раз (предчувствую повторение обсуждения (не-)работоспособности таймеров и пиков в целом ~ полутора-двухмесячной давности). Читайте ДШ про OPTION и pull-up (ЕМНИП, в F84 встроенных WPU нет), ДШ и ман компилятора про прерывания, и конфу про то же самое. Помигайте для начала светодиодом, потом заставьте второй контроллер повторить это миганье - половина _Вашего_ протокола будет готова.
|
|
|
|
|
Jul 17 2011, 19:58
|
Группа: Новичок
Сообщений: 4
Регистрация: 16-07-11
Пользователь №: 66 258

|
Полностью переделал код, задействовав прерывания от таймера. Передачу и приём сделал разной длины..и даже что то у меня получилось...каким то странным образом один - два раза таки зажегся этот светодиод в протеусе..но я думаю это всего лишь случайное совпадение.
Передатчик на двух кнопках:
#include <16f84.h> #use delay(clock=4000000) #fuses XT,NOWDT #byte PORTB = 0x06 #byte TRISB = 0x086 #byte PORTA = 0x05 #byte TRISA = 0x085 #byte INTCON = 0x0B #byte OPTION_REG = 0x081 #byte TMR0 = 0x01 #bit T0CS = OPTION_REG.5 #bit PS0 = OPTION_REG.0 #bit PS1 = OPTION_REG.1 #bit PS2 = OPTION_REG.2 #bit GIE = INTCON.7 #bit T0IE = INTCON.5 #bit T0IF = INTCON.2 char data[]={0,0,0,0}; //Массив, в котором лежат передающиеся биты void dataf1(void); //Функция, изменяющая массив с данными при нажатии кнопки 1 void dataf2(void); //Функция, изменяющая массив с даннми при нажатии кнопки 2 int i=0; //Глобальная переменная- счётчик #int_timer0 //Прерывание по переполнению таймера void timer0_isr() //Функция - обработчик прервывания { T0IF=0; //Сбрасываем флаг прерывания PORTB=PORTB | data[i]; //Логическое ИЛИ, переводящее порт В к состоянию содержимого элемента массива с даннми i++; if (i==4) { T0IE=0; GIE=0; PORTB=0b00000001; } } void main () { TMR0=0; PORTA=0; TRISA=0b1111; PORTB=0b00000001; TRISB=0; while (1) { if (PORTA==0b0001) { PORTA=0; dataf1(); PORTB=0b10000001; PORTB=0b00000001; T0CS=0; PS0=1; PS1=1; PS2=1; T0IE=1; GIE=1;
} else { if (PORTA==0b0010) { PORTA=0; dataf2(); PORTB=0b10000001; PORTB=0b00000001; T0CS=0; PS0=1; PS1=1; PS2=1; T0IE=1; GIE=1; } } } } void dataf1(void) { data[0]=0b00000001; data[1]=0b00000001; data[2]=0b00000001; data[3]=0b10000001; } void dataf2(void) { data[0]=0b00000001; data[1]=0b00000001; data[2]=0b10000001; data[3]=0b00000001; }
Приёмник:
#include <16f84.h> #use delay(clock=4000000) #fuses XT,NOWDT #byte PORTB = 0x06 #byte TRISB = 0x086 #byte INTCON = 0x0B #byte OPTION_REG = 0x081 #byte TMR0 = 0x01 #bit GIE = INTCON.7 #bit T0IF = INTCON.2 #bit T0IE = INTCON.5 #bit T0CS = OPTION_REG.5 #bit PS0 = OPTION_REG.0 #bit PS1 = OPTION_REG.1 #bit PS2 = OPTION_REG.2 char result=0b00000000; int counter=0; char addendum=0b00001000; #int_timer0 void timer0_isr() { T0IF=0; TMR0=39; if (input(PIN_B0)==0) result=result | 0b00000000; else { if (input(PIN_B0)==1) result=result | addendum; } counter++; addendum=addendum>>1; if (counter==4) { T0IE=0; GIE=0; addendum=0b00001000; } }
void main() { TRISB=0b00000001; PORTB=0; while(1) { if (PORTB==0b00000001) { TMR0=39; PS0=1; PS1=1; PS2=1; T0CS=0; T0IE=1; GIE=1; PORTB=0; } if (result==0b00000001) { PORTB=0b10000000; result=0; } } }
Я рассчитал, что прерывания от таймера приёмника будут срабатывать каждые 0,06 секунды, а прерывания от таймера передатчика каждые 0,05. тоесть приёмник считывает состояние порта В в промежутке между прерываниями передатчика. Для фиксации приёма я ввел переменную addendum, которая складывается с result, при каждом новом прерывании. Чтобы обеспечить соответсвие разрядоов я ввел смещение переменной addendum после каждого прерывания.
Сообщение отредактировал FOX_ - Jul 17 2011, 20:01
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|