Перейти к содержанию

Помогите С Uart В Attiny2313


Рекомендуемые сообщения

Добрый день ребят! Помогите пожалуйста с реализацией кода на Attimy2313A с UART

Написал вот такой кодик по примерам:

#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>
#include <stdlib.h>
//макросы вычисления скорости
#define BAUD 19200
#define UBRR_VAL F_CPU/8/BAUD-1
void usart_init(unsigned int speed)
{
// устанавливаем скорость Baud Rate: 9600
UBRRH=(char)(speed>>8);
UBRRL=(char) speed;
UCSRA=0x00;
UCSRB|=(1<<RXEN);// Разрешение работы приемника
UCSRB|=(1<<TXEN); //Разрешение работы передатчика
UCSRB|=(1<<RXCIE);// Разрешение прерываний по приему
// Установка формата посылки: 8 бит данных, 1 стоп-бит
UCSRC=(1<<UCSZ1)|(1<<UCSZ0);
}

//выводим принятый байт на порт
ISR(USART0_RX_vect)
{ PORTB=UDR;
_delay_ms(100);
UDR = PORTB; // "ЭХО"

}
int main(void)
{

usart_init(UBRR_VAL);//инициализация модуля
sei();
DDRB= 0b11111111; //вывод на все пины порта B
while(1);
{
}

Цель текущего кода: принять и отправить по прерыванию. Пробовал тестить в протеусе, что то неочень получается. данные приходят но криво. Приколы с таблицой ASCII я уже просек, поэтому пробовал отправлять с зажатым альтом цифры. Результат неутешил.

Конечный код должен принимать подряд 2 байта, где 1- содержит ИД устройства , если BlockID == 1 байту (где BlockID - const), то второй байт кидаем на PORTB

Главный вопрос, работает ли мой код и как принимать подряд 2 байта в одном прерывании??

Пишу в Atmel Studio 7

Баудрэйт 19200 бод

Частота мк 8МГц

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

О работает!! Стоило макрос подсчета выкинуть и цифру подставить... Хорошо, а как принимать 2 байта в 1 прерывании? Или Сначало принять 1 подождать 2 мс и принять второй?

int Mess1_ID;

int Mess2_Val;

ISR(USART0_RX_vect)

{ Mess1_ID = UDR;

_delay_ms(10);

Mess2_Val = UDR;

if (Mess1_ID == BlockID)

{ PORTB = Mess2_Val;

}

Мне так кажется, что я могу упустить байт следующий.

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

одно прерывание один байт! не важно 1 байт или 100, складывай в массив все что приходит, как заполнится обрабатывай, главное по прерыванию приема udr считывать для освобождения буфера и что бы не пропало.

Изменено пользователем Mishany
Ссылка на комментарий
Поделиться на другие сайты

Мда... собрал на макетке, подключил Arduino UNO R3 к Attiny2313A, что то непашет...

Вот код на Attiny2313a

#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>
#include <stdlib.h>

void usart_init(unsigned int speed)
{
UBRRH=(char)(speed>>8);
UBRRL=(char) speed;
UCSRA=0x00;
UCSRB|=(1<<RXEN);// Разрешение работы приемника
UCSRB|=(1<<TXEN); //Разрешение работы передатчика
UCSRB|=(1<<RXCIE);// Разрешение прерываний по приему
// Установка формата посылки: 8 бит данных, 1 стоп-бит
UCSRC=(1<<UCSZ1)|(1<<UCSZ0);
}
int BlockID = 0b00000001;
int UMESS[2];
int i = 0;
//выводим принятый байт на порт
ISR(USART0_RX_vect)
{ UMESS[i]=UDR;
i++;
if (i==2)
{ if (UMESS[0]==BlockID)
{ PORTB = UMESS[1]; }
i=0;
}
}
int main(void)
{

usart_init(25);//инициализация модуля
sei();
DDRB= 0b11111111; //вывод на все пины порта B
while(1);
{
}

}

А вот на Ардуино

void setup() {
// put your setup code here, to run once:
Serial.begin(19200);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.write(0b00000000);
delay(5);
Serial.write(0b11111111);
delay(100);
Serial.write(0b00000001);
delay(5);
Serial.write(0b11111111);
delay(100);
Serial.write(0b00000001);
delay(5);
Serial.write(0b00000000);
delay(100);
}

Первую пару посылок мк должен проигнорить.

После второй и третьей пары посылок от ардуино, должен зажечся порт B и потухнуть, но ничего непроисходит. Порт всегдя в 0, хотя от Arduino байты идут. Что может быть не так??

Изменено пользователем IntelXerox
Ссылка на комментарий
Поделиться на другие сайты

перед заполнение надо отлавливить каждый байт на поиск BlockID и только после заполнять массив, и еще добавить CRC байт в конце для контроля правильность посылки байт.

Ссылка на комментарий
Поделиться на другие сайты

перед заполнение надо отлавливить каждый байт на поиск BlockID и только после заполнять массив, и еще добавить CRC байт в конце для контроля правильность посылки байт.

Это невозможно, так как второй байт, который содержит Value, может варьировать от 0 до 254, тоесть может совпадать с BlockID. А про CRC впервые слышу, можно поподробней?))

Ссылка на комментарий
Поделиться на другие сайты

если надо передат1 байт:

1 байт - ID устройства если их несколько на шине висит

2 байт - данные

3 байт - CRC контрольная сумма байт3=байт1^байт2 для проверки переданной посылки, так правильнее будет особенно если передавать более 1 байта данных

если CRC не сходится - ошибка передачи, запрос на повтор передачи.

делал ретранслятор на 2313 UART передача 110 байт пакет с 10 CRC с подменой значений.

/*
SELFPRGEN = [ ]
DWEN = [ ]
EESAVE = [X]
SPIEN = [X]
WDTON = [ ]
BODLEVEL = DISABLED
RSTDISBL = [ ]
CKDIV8 = [ ]
CKOUT = [ ]
SUT_CKSEL = EXTXOSC_8MHZ_XX_14CK_4MS1
EXTENDED = 0xFF (valid)
HIGH = 0x9F (valid)
LOW = 0xEF (valid)
2->RX вход
3->TX выход
4,5-> Кварц 20MHz, 2x12pF
6->вход SET
7->вход CRUISE
8->вход //
9->вход //
*/
#define F_CPU 20000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define RX_ON UCSRB=0b10010000
#define TX_ON UCSRB=0b00001000
#define SET (PIND&(1<<2))
#define CRUISE (PIND&(1<<3))
void nalog(void);
void uart_puts(unsigned char c);
unsigned char maska;
unsigned char i,j,dat,a,b;
unsigned char data[10][11];
void UART_init(void)
{
DDRD|=(1<<1)|(1<<4)|(1<<5);
PORTD|=(1<<1)|(1<<0)|(1<<2)|(1<<3);
UBRRH=0;		   //14400
UBRRL=86;
UCSRC|=(1<<UCSZ0)|(1<<UCSZ1)|(1<<UPM1)|(1<<UPM0);
UCSRB|=(1<<RXEN)|(1<<RXCIE)|(1<<TXEN);
}

ISR(USART_RX_vect)
{
dat=UDR;
maska|=(1<<2);
if (dat==160)
{
 maska|=(1<<1);
 i=0;
 j=0;
}
}
void nalog(void) //функци обработки массива
{
for (i=1;i<10;i=i+2) //перебор каждого нечетного пакета
{
 data[i][3]=data[i][3]^b; //наложение SET
 data[i][4]=data[i][4]^a; //наложение CRUISE
 data[i][10]=data[i][1]^data[i][2]^data[i][3]^data[i][4]^data[i][5]^data[i][6]^data[i][7]^data[i][8]^data[i][9]; //контрольная сумма
}
maska|=(1<<0); //разрешить передачу UART
}
void uart_puts(unsigned char c)
{
while((UCSRA&(1<<UDRE))==0);
UDR=c;
}
int main(void)
{
maska=0;
UART_init();
sei();
while(1)
{
 if (CRUISE!=0)
 {
  a=32;
 }
 else
 {
  a=0;
 }
 if (SET!=0)
 {
  b=8;
 }
 else
 {
  b=0;
 }
 if ((maska&(1<<0))!=0)
 {
  for (j=0;j<10;j++)
  {
   _delay_ms(2);
   for (i=0;i<11;i++)
   {
 uart_puts(data[j][i]);
   }
  }
  RX_ON;
  maska&=~(1<<0);  //запретить передачу UART
 }
if ((maska&(1<<2))!=0)
{
 if ((maska&(1<<1))!=0)
 {
  data[j][i++]=dat;
  if (i>10)
  {

   if (j==9)
   {
 i=0;
 maska&=~(1<<1);
 TX_ON;
 nalog();
   }
   else
   {
 j++;
 i=0;
   }
  }
  maska&=~(1<<2);
 }
}
}
}

Изменено пользователем Mishany
Ссылка на комментарий
Поделиться на другие сайты

Хмм... ща попробую. Если у меня работает ЮАРТ я могу задействовать PORTD 2-5?

Хочу вывести на ногу сигнал если контрольная сумма неверна и попробовать снова...

Ссылка на комментарий
Поделиться на другие сайты

UART занимает только 2 порта, на остальные не влияет

еще можно вылавливать пару байт ID/data по таймауту пары пускать через задержку....

вместо ардуны лучше эксперементировать на PC через терминал и переходник USB-UART

Изменено пользователем Mishany
Ссылка на комментарий
Поделиться на другие сайты

кажется я понял в чем трабл.... Фьюзы заводские стоят же.... как при помощи Sina прог прошить фьюзы на 8 мгц)) а помот перепрошить, что бы кварц подключить на 8

Ссылка на комментарий
Поделиться на другие сайты

Со фьюзами все норм, а все равно ничего не получается... уже разучился и светодиодом моргать или я не понимаю как работать с этими регистрами?

while(1);

{

PORTD |= 1<<PORTD6;

_delay_ms(100);

PORTD |= 1<<PORTD6;

_delay_ms(100);

}

Как нужно корректно устанавливать 1 бит во всем регистре?

Ссылка на комментарий
Поделиться на другие сайты

О отлично, теперь светодиод моргает, точка с запятой была после введения цикла из-зи этого тело цикла и не прорабатывало. Пробую сделать CRC проверку... компилятор ругается... как правильно оформить этот кусок кода?


ISR(USART0_RX_vect)
{ UMESS[i]=UDR;
i++;
if (i==3)
{ if (UMESS[0]^UMESS[1] == UMESS[2])
{
if (UMESS[0]==BlockID)
{ PORTB = UMESS[1]; }
} else  {
PORTD |= (1<<6);
_delay_ms(200);
PORTD &= ~(1<<6);
}
i=0;
} 
 }




Пояснение: после приема всех трех байтов идет проверка CRC байта, если тот верный, то выполняем код дальше. Если нет,то горим красным светодиодом на PD6 и завершаем код прерываний (обнуляем переменную после эксплуотации)

Ссылка на комментарий
Поделиться на другие сайты

хотя бы так: было куча ошибок, и код хотя бы форматируй, а то не читаем..

ISR(USART0_RX_vect)
{
UMESS[i]=UDR;
i++;
if (i>1)
{
if ((UMESS[0]^UMESS[1]) == UMESS[2])
{
if (UMESS[0]==BlockID)
{
PORTB = UMESS[1];
}
else
{
PORTD |= (1<<6);
_delay_ms(200);
PORTD &= ~(1<<6);
}
// i=0;
}
i=0;
}
}

так будет более правильно (не нагружая прерывание):

uint8_t BlockID,flag,i;
ISR(USART0_RX_vect)
{
UMESS[i++] = UDR; //инкоимент i послежнее действие в этом операторе
if (i>1) //если i=2 приняли 3 байта
{
 i = 0;
 flag = 1;
}
}
int main(void)
{
//настройка перефирии
sei();//глобально разрешаем прерывания
while(1)
{
 if (flag == 1)
 {
  if ((UMESS[0]^UMESS[1]) == UMESS[2])
   {
   if (UMESS[0]==BlockID)
 {
 PORTB = UMESS[1];
 }
   else
 {
 PORTD |= (1<<6);
 _delay_ms(200);
 PORTD &= ~(1<<6);
 }
   }
  flag = 0;
 } 
}
}

Изменено пользователем Mishany
Ссылка на комментарий
Поделиться на другие сайты

Вообщем, собрал снова на макетке с исправлением всех замечаний и ошибок, подрубил Ардуино, предварительно результат проверки CRC вывел на второй светодиод. Получается 1 показывает что МК не повис, а второй сигналит где битые байты... Ошибок много, 20% он все таки принимает как верные, вот только сигнала на порте PORTB так и нет...

ISR(USART0_RX_vect)
{ UMESS[i]=UDR;
i++;
if (i==3)
{ if ((UMESS[0]^UMESS[1]) == UMESS[2])
 {
  if (UMESS[0]==BlockID)
  { PORTB = UMESS[1]; }
 } else  {
   PORTD |= (1<<5);
   _delay_ms(10);
   PORTD &= ~(1<<5);
   }
 i=0;
}
 }

int main(void)
{

usart_init(25);//инициализация модуля
sei();
DDRB= 0b11111111; //вывод на все пины порта B
DDRD|=(1<<6)|(1<<5);
while(1)
 {
 PORTD |= (1<<6);
 _delay_ms(10);
 PORTD &=~(1<<6);
 _delay_ms(500);



 }

}

Пояснение: Прерывание работает как и раньше, принимает 3 байта по счетчику i, когда тот равен 3, то сверяем байты, если не битые выполняем управление портом B, если битые - сигнализируем светодиодом.

В Мэйне инициализация портов как выходы и в бесконечном цикле дергаем светодиод, сигнализируя, что мы еще живы.

Ссылка на комментарий
Поделиться на другие сайты

i==3 это означает что должно приняться 4 байта, а если вдруг i=4 как поведет себя программа?

использование задержки в прерывании это ужас...

скобки фигурные кто будет исправлять?:

{ PORTB = UMESS[1]; }

} else {

Изменено пользователем Mishany
Ссылка на комментарий
Поделиться на другие сайты

i == 3 - все верно, так как перед сравнением идет инкремент i++ поэтому когда принят третий байт, идет i++ и i уже содержит 3, а скобки не заметил, ща поправим))

Задержки в прерывании я просчитал, у Arduino тоже стоят задержки между байтами 20мс , а между пакетами 500мс)

стоп, так скобки правильные...

if (проверяем CRC)
{
  if (проверяем ИД)
         { включаем/выключаем портБ
         }
} else {

морг... морг

}

Ссылка на комментарий
Поделиться на другие сайты

Вообщем, я поместил в тело ифы, которая сверяет байты, код моргания светодиодом, в том же теле включается и выключается портБ.

Светодиод не моргает в тоже время как светодиод ошибки передачи молчит, получается, что тинка из-за РЦ генератора пропускает те байты и это значит, что тело ифы "Если верно" совершенно не выполняется, те условие

if ((UMESS[0]^UMESS[1]) == UMESS[2])

сегда неверно. В ардуине я ксоры подсчитывал на калькуляторе))... даже не знаю в чем может быть и проблемма.....

Вот код Ардуинки если понадобится)

void loop() {
 // put your main code here, to run repeatedly:
Serial.write(1); //1 й байт ИД
delay(20);
Serial.write(255);  //2 байт Валуе
delay(20);
Serial.write(254); // 3 байт КСОР
delay(1000);
Serial.write(1); //1 байт
delay(20);
Serial.write(0); //2 байт
delay(20);
Serial.write(1); //3 байт ксор
delay(1000);
}

Изменено пользователем IntelXerox
Ссылка на комментарий
Поделиться на другие сайты

прием сработает при посылке 4 байта если отправить 3 байта условие не сработает либо будет постоянный сдвиг

так работает?

ISR(USART0_RX_vect)

{

PORTB = UDR;

}

Изменено пользователем Mishany
Ссылка на комментарий
Поделиться на другие сайты

если горит весь порт то прием не правильный скорее всего, в UDR может быть постоянно 0xFF - будет гореть весь порт, для начала надо проверить правильность передачи одного байта, и только потом думать о передачи посылок.

скорее всего не совпадает скорость

подключение правильное?

Rx --> Tx

Tx --> Rx

каждую сек в цикле на ардуне передавать 1, 2, 4, 8, 16, 32, 64, 128 должен получиться бегущий огонек.

Изменено пользователем Mishany
Ссылка на комментарий
Поделиться на другие сайты

тогда вот пробуй:

#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
void proverka(void);
unsigned char flag=0,BlockID=1;
unsigned char i,temp;
unsigned char data[3];// массив для хранения {ID, DATA, CRC}
void UART_init(void)
{
//личные настройки UART
}
void PORTS_init(void)
{
//личные настройки портов
}
ISR(USART_RX_vect)
{
temp=UDR;
flag|=(1<<2);
//далее отлавливаем свой ID, и запускаем заполнение массива в основном цикле.
if ((temp==BlockID)&&((flag&(1<<0))==0))
{
 flag|=(1<<1)|(1<<0);
 i=0;
}
}
void proverka(void) //функци обработки массива
{
if (data[2] == (data[0]^data[1]))
{
 //делаем чтото, если контрольная сумма сошлась...
}
else
{
  //делаем чтото, если ошибка контрольной суммы
}
}
int main(void)
{
PORTS_init();
UART_init();
sei();
while(1)
{
if ((flag&(1<<2))!=0)
{
 //условие ожидания ID
 if ((flag&(1<<1))!=0)
 {
  data[i++]=temp;
  if (i>2)
  {
 i=0;
 flag&=~((1<<1)|(1<<0));//сбрасывайм флаг для отлавливания ID
 proverka();
  }
  flag&=~(1<<2);
 }
}
}
}

Ссылка на комментарий
Поделиться на другие сайты

А что за флаги? интересно как работает код...

я кс делал простой цикл от 0 до 255 и посылал, так я проверил, что передача идет и тинька ее принимает... Вернулся к коду и просто выводил 2 байт без проверки ИД и CRC, заметил, что тинка работает несинхронно с ардуинкой, иногда принимая байт Value за ИД байт

использовать задержки в прерывании, реально, не очень хорошо))))))

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...