реклама на сайте
подробности

 
 
> PIC 16F84. Последовательная передача через порт
FOX_
сообщение Jul 16 2011, 19:13
Сообщение #1





Группа: Новичок
Сообщений: 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;
}
}

Идея в том, что по нажатию кнопки выполняется какое то действие. Для примера я сделал, чтобы загорался светодиод...только ничего не происходит

Вот грубая схемка этого чудо устройства

Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 6)
Danis
сообщение Jul 16 2011, 21:10
Сообщение #2


Twilight Zone
***

Группа: Свой
Сообщений: 454
Регистрация: 17-02-09
Из: Челябинск
Пользователь №: 44 990



Ни хочу мешать Вашим экспериментам, но советую последовательно с любым из испытуемых пинов микроконтроллера включать токоограничивающий резистор, например 1K. Порты надо беречь!


--------------------
Magic Friend
Go to the top of the page
 
+Quote Post
FOX_
сообщение Jul 16 2011, 21:14
Сообщение #3





Группа: Новичок
Сообщений: 4
Регистрация: 16-07-11
Пользователь №: 66 258



Так не получается ничего....не работает моя прошивка..может подскажите что в ней не так?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 16 2011, 21:31
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



QUOTE (FOX_ @ Jul 16 2011, 23:14) *
..не так?

не так то, что Вы начали задавать вопросы НЕ в разделе для начинающих. Читать 9001 раз кусок кода UART не работающий в симуляторе мало кому интересно. Локализуйте проблему для начала.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
FOX_
сообщение Jul 16 2011, 21:55
Сообщение #5





Группа: Новичок
Сообщений: 4
Регистрация: 16-07-11
Пользователь №: 66 258



Получается, что я как бы свой протокол написал..только нерабочий)) ВСё это работает очень просто. Нажав кнопку, я инициализирую процесс передачи, который заключается в следующем: сначала передаётся старт бит, равный 1, потом включается таймер и пока он не будет сброшен (это примерно 0,06секунды) передается следующий бит..и т.д. В моём случае я передаю всего полбайта, что соответсвует номеру нажатой кнопки (1,2,3 и т.д...на схеме представлена только одна для простоты описания). Чтобы начать считывать приёмник ждёт старт бита 1. Получив его, он также в течении 0,06 секунды считывает состояние на входящей ножке и записывает результат в переменную. По идеи всё должно работать, но не работает...может код корявый?))Теория то впринципе верна..
Go to the top of the page
 
+Quote Post
xemul
сообщение Jul 17 2011, 12:01
Сообщение #6



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(FOX_ @ Jul 17 2011, 01:55) *
По идеи всё должно работать, но не работает...может код корявый?))Теория то впринципе верна..

Увы, проги работают не за идею или теорию, а в соответствии с понаписатым.
Подобные ошибки обсасывались стотыщьпицот раз (предчувствую повторение обсуждения (не-)работоспособности таймеров и пиков в целом ~ полутора-двухмесячной давности).
Читайте ДШ про OPTION и pull-up (ЕМНИП, в F84 встроенных WPU нет), ДШ и ман компилятора про прерывания, и конфу про то же самое.
Помигайте для начала светодиодом, потом заставьте второй контроллер повторить это миганье - половина _Вашего_ протокола будет готова.
Go to the top of the page
 
+Quote Post
FOX_
сообщение Jul 17 2011, 19:58
Сообщение #7





Группа: Новичок
Сообщений: 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
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 26th July 2025 - 01:34
Рейтинг@Mail.ru


Страница сгенерированна за 0.01426 секунд с 7
ELECTRONIX ©2004-2016