Программный UART для любого микроконтроллера. Модификация кода для AVR. Ч2

09/02/2012 - 20:04
   Перейдем к модификации описанного программного UART`a под конкретный камушек. Поскольку пишу я в основном про 8-ми разрядные AVR, то эти контроллеры и будем рассматривать. 
   Во всех микроконтроллерах семейства mega есть аппаратный модуль UART, а вот в микроконтроллерах семейства tiny нет. По идее программный UART может потребоваться именно для младшего семейства, но не исключаю возможность использования этого кода и в mega`ах. Пути эмбеддера неисповедимы.       
   Проекты написаны в двух вариантах – для ATTiny45 и для ATmega16. Впрочем, отличия там очень незначительные и касаются только инициализации и прерывания задействованного таймера. 

Программный UART для Tiny45. Заголовочный файл

   Первое, что я сделал - это создал заголовочный файл softUart.h. В него я прописал включение заголовочного файла compilers_3.h, обеспечиващего совместимость с тремя AVR компиляторами (IAR, CodeVision, GNU GCC), макроопределения и прототипы пользовательских функций. Прототипы, следуя своему стилю, обозвал с использованием приставки. В данном случае - “SUART_”. Это позволяет легко определять, к каким файлам относятся те или иные функции. 

#ifndef SOFT_UART_H
#define SOFT_UART_H

#include "compilers_3.h"

/*___________________________Настройки_____________________________________*/

/*тактовая частота мк*/
#ifndef F_CPU
#define F_CPU 8000000L
#endif

/*прескалер таймера 1L, 8L, 64L, 256L, 1024L*/
#define SUART_PRESCALER 1L

/*скорость обмена*/
#define SUART_BAUD_RATE 19200L

/*вместимость приемного буфера*/
#define SUART_BUF_SIZE 32

/*пин приемника*/
#define RX_PINX PINB
#define RX_PORTX PORTB
#define RX_DDRX DDRB
#define RX_PIN 1

/*пин передатчика*/
#define TX_PORTX PORTB
#define TX_DDRX DDRB
#define TX_PIN 0

/*функция или макрос, выполняемый во время
ожидания поступления данных в приемный буфер.
она запускается в функции SUART_GetChar()*/
#define SUART_Idle()

/*________________________Пользовательские функции___________________________*/

void SUART_Init(void);
char SUART_GetChar(void);
void SUART_PutChar(char ch);
void SUART_PutStr(char *str);
void SUART_PutStrFl(char __flash *str);
void SUART_FlushInBuf(void);
char SUART_Kbhit(void);
void SUART_TurnRxOn(void);
void SUART_TurnRxOff(void);

/*___________________________________________________________________________*/

#endif //SOFT_UART_H
 

 
   Макроопределения F_CPU, SUART_PRESCALER и SUART_BAUD_RATE используются в макросе расчета таймерной константы, обеспечивающей заданную скорость обмена по UART`у. Константа SUART_PRESCALER может принимать только значения, записанные в комментарии - 1L,8L,64L,256L,1024L. При задании других значений, компилятор будет выдавать ошибку. Также компилятор будет выдавать ошибку, если при расчете таймерной константы будут получаться недопустимые значения - ноль и значения больше 256, и предупреждения, если получаемая скорость программного UART`a будет на 1% больше или меньше требуемого значения.   
  Также в заголовочный файл я добавил определения, задающие приемный и передающий вывод микроконтроллера.

Программный UART для Tiny45. Сишный файл

   В сишный файл, я добавил макросы, используемые для обращения к приемному и передающему выводу микроконтроллера. 
 
#define get_rx_pin_status()    RX_PINX & (1<<RX_PIN)
#define set_tx_pin_high()      TX_PORTX |= (1<<TX_PIN)
#define set_tx_pin_low()       TX_PORTX &= ~(1<<TX_PIN)
 

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

#define TIME_VALUE (F_CPU/(SUART_BAUD_RATE*NUM_OF_CYCLES*SUART_PRESCALER))
#define TIMER_TCNT_VALUE (0xff - (TIME_VALUE - 1))
#define ERROR_VALUE ((F_CPU*100)/(TIME_VALUE*SUART_BAUD_RATE*NUM_OF_CYCLES*SUART_PRESCALER))

#if ((TIME_VALUE > 256)||(TIME_VALUE == 0))
#error "TIMER_TCNT_VALUE is not correct. Change PRESCALER, BAUD_RATE or F_CPU"
#endif

#if ((ERROR_VALUE > 100)||(ERROR_VALUE < 100))
#warning "Baud rate error > 1%"
#endif

#if SUART_PRESCALER==1L
   #define CSXX (0<<CS02)|(0<<CS01)|(1<<CS00)
#elif SUART_PRESCALER==8L
   #define CSXX (0<<CS02)|(1<<CS01)|(0<<CS00)
#elif SUART_PRESCALER==64L
   #define CSXX (0<<CS02)|(1<<CS01)|(1<<CS00)
#elif SUART_PRESCALER==256L
   #define CSXX (1<<CS02)|(0<<CS01)|(0<<CS00)
#elif SUART_PRESCALER==1024L
   #define CSXX (1<<CS02)|(1<<CS01)|(1<<CS00)
#else
   #error "prescaller not correct"
#endif
 
   Функции void timer_set( int BAUD_RATE ) и void set_timer_interrupt( timer_isr ) удалил, а функцию инициализации программного UART`a, из которой они вызывались, подправил следующим образом. 
 
 

void SUART_Init(void)
{
   /*инициализация флагов*/
   flag_tx_busy = FALSE;
   flag_rx_ready = FALSE;
   flag_rx_waiting_for_stop_bit = FALSE;
   flag_rx_off = FALSE;

   /*настройка выводв*/
   RX_DDRX &= ~(1<<RX_PIN);
   RX_PORTX |= (1<<RX_PIN);
   TX_DDRX |= (1<<TX_PIN);
   TX_PORTX |= (1<<TX_PIN);

   /*настройка таймера Т0*/
   TCCR0B = CSXX;
   TCNT0 = TIMER_TCNT_VALUE;
   TIMSK |= (1<<TOIE0);
}
 
   Как видите, я задействовал 8-ми разрядный таймер Т0 в режиме NORMAL с прерыванием по событию «переполнение». Предделитель таймера (CSXX) определяется константой SUART_PRESCALER, а таймерная константа TIMER_TCNT_VALUE  вычисляется с помощью макроса. 
 
   Основной код программного UART`a поместил в обработчик прерывания таймера Т0, добавив в его начало код перезаписи значения счетного регистра TCNT0.  Лучшим вариантом было бы использование режима СТС, но этот режим у 8-ми разрдядных таймеров иногда отсутствует.
 
ISR(TIM0_OVF_VECTOR)
{
   uint8_t start_bit, flag_in;
   uint8_t rx_data;
   static uint16_t internal_rx_buffer;

TCNT0 += TIMER_TCNT_VALUE;
    …..
    //основной код
    ….
}

   Не удивляйтесь, что обработчик пррывания выглядит не так как принято в IAR`е. Просто объявление прерывания "запаковано" в макросе ISR. Это было сделано с целью совместимости кода с несколькими компиляторами. (Написание нескольких проектов отнимает много времени, не говоря уже об их дальнейшем исправлении. )

  Следующая доработка кода программного UART`a – добавление квалификатора volatile к  переменным, который используются и в прерывании и в обычных функциях. 

static volatile uint8_t inbuf[SUART_BUF_SIZE];
static volatile uint8_t qin = 0;
static volatile uint8_t qout = 0;

static volatile uint8_t flag_rx_ready;
static uint8_t flag_rx_waiting_for_stop_bit;
static uint8_t flag_rx_off;
static uint8_t rx_mask;
static uint8_t timer_rx_ctr;
static uint8_t bits_left_in_rx;

static volatile uint8_t flag_tx_busy;
static volatile uint8_t timer_tx_ctr;
static volatile uint8_t bits_left_in_tx;
static volatile uint16_t internal_tx_buffer;
 
  И в заключении, я добавил функции вывода строк из ОЗУ и из flash памяти. 

void SUART_PutStr(char *str)
{
   char ch;
   while (*str){
      ch = *str++;
      SUART_PutChar(ch);
   }
}


void SUART_PutStrFl(char __flash *str)
{
   char ch;
   ch = read_byte_flash(*str);
   while (ch) {
      SUART_PutChar(ch);
      str++;
      ch = read_byte_flash(*str);
   }
}


   Далее я сделал проект в IAR`е, подключил к нему полученную «либу» программного UART`а и написал пару строк кода для проверки результатов. Остальные изменения в коде касались небольшой оптимизации, про них я говорить не буду. 

   Думаю, теперь вы без проблем модифицируете этот софтовый UART под любой другой камень.

Файлы

Комментарии   

# Petrov 21.02.2012 14:52
Спасибо Pashgan. Подскажи пожалуйста, представленный тобой код позволит принять строку? Дело в том, что я делал программный uart и у меня не получилось допилить свою прошивку до возможности приема строки. На втором символе кристалл затыкался.
Ответить | Ответить с цитатой | Цитировать
# NeoMage 15.03.2012 17:15
Сколько SUART 9600 можно реализовать на ATMega16 или на ATMega88?
Ответить | Ответить с цитатой | Цитировать
# vovo5762 30.08.2012 12:01
Спасибо, очень помогло. Есть маленькое замечание. Переменная internal_tx_buf fer должна быть типа short, иначе передаётся только таблица ASCII7. Справедливо и для rx, но критично.
Ответить | Ответить с цитатой | Цитировать
# Airbus 04.09.2012 15:42
Спасибо хорошо написано.А как сделать для 13 тинюхи?Подправи ть названия регистров?
Ответить | Ответить с цитатой | Цитировать
# Pashgan 04.09.2012 21:58
Для Tiny13 нужно:
- исправить регистр TIMSK на TIMSK0 в функции инициализации
- правильно установить fuse бит CLKDIV8, чтобы тактовая частота контроллера не делилась на 8.
- уменьшить размер буфера IN_BUF_SIZE и размеры стеков CSTACK, RSTACK, потому что ОЗУ у tiny13 меньше, чем у tiny45
ну и вроде все...
Ответить | Ответить с цитатой | Цитировать
# dim 19.07.2014 15:57
Не помогает((
Ответить | Ответить с цитатой | Цитировать
# sasha-posit 03.10.2012 17:26
здравствуйте, я пользуюсь этим примером давно, все работает ок! но вот захотелось поспробовать реализовать 2-а таких уарта на меге 32, но что-то так и не получается. Как правильно это сделать???
Ответить | Ответить с цитатой | Цитировать
# Pashgan 04.10.2012 03:50
Сразу не могу сказать. Если на выходных будет время, попробую что-нибудь накатать. А тебе нужно чтобы они и на прием и на передачу работали или что то одно? Попробуй для начала скорость обмена снизить до минимума.
Ответить | Ответить с цитатой | Цитировать
# sasha-posit 04.10.2012 07:04
да дело в том что и на прием и передачу надо чтоб работали, я скорость снижал, первый работает, а второй нет. я организовал так: скопировал softuart.c,soft uart.h с другими именами, подключил их, изменил название всех переменных в этих файлах, но ничего так и не происходит, первый работает, а второй нет.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 04.10.2012 09:36
Нужно переделать функцию GetChar, тогда должно заработать.
Ответить | Ответить с цитатой | Цитировать
# sasha-posit 04.10.2012 10:00
только ее нужно переделать?, и что именно в ней изменить
Ответить | Ответить с цитатой | Цитировать
# Pashgan 04.10.2012 11:21
Функция опрашивает приемный буфер. Если он пустой, она ждет когда придут данные. Этот момент и нужно изменить. Если подождешь до вечера, скину свой код. Только он написан на скорую руку, без претензий на оптимальность.
Ответить | Ответить с цитатой | Цитировать
# sasha-posit 04.10.2012 12:43
ок, конечно подожду:)
Ответить | Ответить с цитатой | Цитировать
# sasha-posit 04.10.2012 12:44
а вы с какой страны, у нас уже вечер:)
Ответить | Ответить с цитатой | Цитировать
# Pashgan 04.10.2012 17:04
Из России матушки..
Архив проекта выложил на форуме.
Ответить | Ответить с цитатой | Цитировать
# sasha-posit 06.10.2012 06:17
спасибо, буду разбираться!
Ответить | Ответить с цитатой | Цитировать
# Vadim 23.10.2012 19:34
Попробовал на Меге8 , с кварцем 110592Мгц Proteus показывает что с UART приходит каша. При 16Мгц все нормально,скоро сть правда у меня 9600. Может кто проверит будет ли Мега 8 нормально работать в Proteus с кварцем 110592 и на скорости 9600. Хочу понять это я где-то ступил или глючит Prot.
Ответить | Ответить с цитатой | Цитировать
# Vadim 28.10.2012 13:21
Ну ппц, объясните , почему на меге8 с кварцем 110592 на скорости 9600 программный UART не работает(шлет кракозябры. Его вообще реально запустить нормально с такой скорость при таком кварце?
На 16мгц проблем нет, на скорости 9600 все работает.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 28.10.2012 17:24
Видимо не хватает быстродействия микроконтроллер а для обработки кода прерывания. У меня тоже не получилось запустить программный уарт на скорости 9600 при кварце 11.0592 МГц. На скорости 4800 худо бедно работает. Можно ли запустить? Думаю, да если оптимизировать или переписать код.
Ответить | Ответить с цитатой | Цитировать
# Radioded 24.03.2013 15:48
У меня на ATmega168 @8MHz заработало на 9600, правда пришлось поиграться с прескайлером и значением TCNT0.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 24.03.2013 16:05
Я скоро выложу исправленный проект. Внес несколько мелких правок и код стал исправно работать и на 9600 и на скоростях повыше.
Ответить | Ответить с цитатой | Цитировать
# Андрей888 07.11.2012 09:11
На Казусе нашли косяк в проге http://kazus.ru/forums/showthread.php?t=102587
Ответить | Ответить с цитатой | Цитировать
# Pashgan 07.11.2012 21:25
Были подозрения, что проблема в расчете таймерной константы. Ну что ж, придется исправлять.
Ответить | Ответить с цитатой | Цитировать
# Petrov 11.11.2012 10:42
Подскажите на 8 Мгц заработает при скорости 9600L? Пробую завести на atmega64. Подскажите, какие при этом настройки необходимо произвести?
Ответить | Ответить с цитатой | Цитировать
# McAron 18.12.2012 22:55
А есть ли возможность пользовать программный uart на частоте 16,5MHz?
мне нужно связать два Attiny85 по SoftwareUART, и поподключать каждый к компу через usb. Но как я понял, реализация vusb для attiny85 возможна лишь на скорости 16,5MHz
Ответить | Ответить с цитатой | Цитировать
# Pashgan 19.12.2012 20:34
Возможность есть, а как это будет работать, не могу сказать. Надо проверять.
Ответить | Ответить с цитатой | Цитировать
# ZiperRUS 29.12.2012 14:04
чёто я не пойму так как поменять скорость то? у меня 16М резонатор надо скорость 19200 как её выставитЬ? при замене консканты скорости обмен нарушаеться!!!! это он только на 4800 только настроен чтоль тогда зачем константа юта и зачем людей обманываать
Ответить | Ответить с цитатой | Цитировать
# Snake 23.02.2013 13:05
Pashgan, а что бы значило в putchar:Код:internal_tx_buffer = (user_tx_buffer<<1) | 0x200;. К чему тут 0х200? Или вот в GetChar: Код: ch = inbuf[qout] & 0xFF;?
Ответить | Ответить с цитатой | Цитировать
# Pashgan 23.02.2013 13:44
Данная строчка формирует кадр, который будет передаваться по UARTу. Кадр состоит из стартового бита, данных и стопового бита. Стоповый бит всегда 1. Данные передаются младшим разрядом вперед.
Код:internal_tx_buffer = (user_tx_buffer<<1) | 0x200;
Байт данных сдвигается на один разряд влево и в 10-ом разряде устанавливается единица (0x200 - это 1000000000 в двоичном коде). Это единица и есть стоповый бит.
Смысл второй строчки объяснить не могу. Понятно, что это маска, но зачем она здесь не знаю.
Ответить | Ответить с цитатой | Цитировать
# Snake 23.02.2013 19:52
Ну да, я всё понимаю, только internal_tx_buf fer, как и user_tx_buffer имеют тип сhar? К чему сдесь 0x200? Вопрос по прежнему.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 23.02.2013 21:13
Не обратил внимание, был уверен, что они типа int. Слушай, по ходу ошибка. Я нашел обсуждение этого кода на одном из зарубежных форумов. Там есть сообщения про эти строчки и народ говорит, что должен быть тип int.
Ответить | Ответить с цитатой | Цитировать
# Snake 24.02.2013 06:02
Похоже. Это то что сразу бросилось в глаза. Причём, и в других реализациях, кочует просто.((
Ответить | Ответить с цитатой | Цитировать
# Pashgan 24.02.2013 14:05
Будем исправлять..
Ответить | Ответить с цитатой | Цитировать
# Михалыч 01.05.2013 13:07
Здравствуйте уважаемый Pashgan. Спасибо за либы, просимулировал в протеусе проверил, работает но до тех пор пока кидаешь одиночные символы. При попытке отправить контроллеру строку например из 10 символов получаем эдак второй, пятый остальные либо мусор либо теряем. Подкажите пожалуйста в чём можт быть проблема, куда смотреть что предпринять, работаю при следующих настройках скорость 1200 бод, один стопбит, без проверки чётности, заранее благодарен.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 01.05.2013 20:44
После праздников выложу исправленный вариант. Сейчас в коде есть ошибки.
Ответить | Ответить с цитатой | Цитировать
# Михалыч 02.05.2013 19:57
Большое спасибо за скорый ответ.
Ответить | Ответить с цитатой | Цитировать
# Михалыч 16.05.2013 09:31
Извините за наглость, когда будет исправленный вариант, праздники прошли, очень жду. Заранее благодарен.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 17.05.2013 17:28
Статья исправлена, проекты перезалиты.
Ответить | Ответить с цитатой | Цитировать
# dax4 03.05.2013 10:37
Как сделать проверку, что uart готов к передачи? Просто мне надо отправлять под ряд много символов.
Ответить | Ответить с цитатой | Цитировать
# Михалыч 04.05.2013 15:28
Разрешите вмешаться:) для отправления строки я написал такую функцию:
void PutStr(char* s)
{
SUART_TurnRxOff();
for (is=0; is
Ответить | Ответить с цитатой | Цитировать
# Михалыч 04.05.2013 15:33
Простите, добавилось не полностью.
void PutStr(char* s)
{
SUART_TurnRxOff();
for (is=0; is
Ответить | Ответить с цитатой | Цитировать
# Михалыч 04.05.2013 15:37
Код:void PutStr(char* s)
{
SUART_TurnRxOff();
for (is=0; is<=(strlen(s)-1); is++) SUART_PutChar(s[is]);
SUART_TurnRxOn();
}
Проверка готовности выполняется внутри функций библиотеки, погуглив для себя сделал вывод, если товарищ Pashgan исправит упомянутые выше ошибки данный драйвер считаю наиболее удачным.
Ответить | Ответить с цитатой | Цитировать
# dax4 17.05.2013 19:25
Подскажите как настроить uart на 9600.
Ответить | Ответить с цитатой | Цитировать
# dax4 17.05.2013 19:37
Частота 8 мгрц.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 17.05.2013 19:54
установить в заголовочном файле
F_CPU 8000000L
SUART_PRESCALER 8L
SUART_BAUD_RATE 9600L
Ответить | Ответить с цитатой | Цитировать
# dax4 18.05.2013 08:14
Он ошибку выдает: 1%
Ответить | Ответить с цитатой | Цитировать
# Pashgan 18.05.2013 09:07
Это не ошибка, это предупреждение. При частоте 8МГц нельзя подобрать такой период таймера, который бы давал ошибку меньше 1%. Если поставить предделитель 1, то расчетное значение будет больше 256, что тоже не подходит.
Ответить | Ответить с цитатой | Цитировать
# vadim 06.09.2013 10:27
Хотел узнать, так может контроллер принимать строку или нет? у меня нормально читает только первый символ, остальное каша.Отправляет данные пакетом нормально, а вот прием нормальный только посимвольный при приходе строки все нарушается кроме первого символа. использовал старые исходники , может в новых что то исправлено для приема строки?
Ответить | Ответить с цитатой | Цитировать
# Pashgan 06.09.2013 11:16
Такой функции там нет. Нужно добавлять.
Ответить | Ответить с цитатой | Цитировать
# vadim 06.09.2013 10:33
Что то скачал исходник для CV , а в архиве лежит для IAR, где взять для CV?
Ответить | Ответить с цитатой | Цитировать
# vadim 06.09.2013 10:35
Цитирую vadim:
Что то скачал исходник для CV


для мега16
Ответить | Ответить с цитатой | Цитировать
# Pashgan 06.09.2013 11:17
Только что скачал SUART- Mega16-CV.rar и проверил. Там архив для Code Vision AVR.
Ответить | Ответить с цитатой | Цитировать
# vadim 06.09.2013 11:51
так а что на счет приема строки на скорости 9600? эта проблема решаема или нет? спасибо за оперативный ответ .
Ответить | Ответить с цитатой | Цитировать
# Pashgan 06.09.2013 12:01
Думаю да, но я не пробовал. По хорошему, нужно добавить туда кольцевой буфер и сделать прием и передачу через него.
Ответить | Ответить с цитатой | Цитировать
# vadim 06.09.2013 11:54
Скачал опять, всетаки там для iar,Author(s).. .: Pashgan http://ChipEnable.Ru
//
// Target(s)...: любой AVR контроллер
//
// Compiler....: IAR 5.11A
//
// Description.: Драйвер программного UART`a на микроконтроллер ах AVR.
// Код написан с использованием appnote фирмы IAR.
//
// Data........: 05.03.13

Да проект , под CV , но содержимое IAR
Ответить | Ответить с цитатой | Цитировать
# Pashgan 06.09.2013 12:03
Просто забыл стереть это. Этот файл для всех компиляторов одинаковый, благодаря compiler_3.h.
Ответить | Ответить с цитатой | Цитировать
# vadim 06.09.2013 12:21
А как быть с этим
обработчик прерывания в СV
interrupt [TIM0_OVF] void tim0_ovf(void)

обработчик прерывания в твоем архиве
ISR(TIM0_OVF_VECTOR)

CV, даже не пытается компилировать проект, many error.

Ну самое главное не это, может ли софтовый UART принимать строку а не побайтно? Просто если это не возможно нет смысла делать дальше , итак целый день убил на проект, все заработало , а с приемом строки вышел облом
Ответить | Ответить с цитатой | Цитировать
# Pashgan 06.09.2013 12:55
ISR разворачивается с помощью compiler_3.h как нужно для CV. Этот проект был скомпилирован с CV и проверен на работоспособнос ть. Иначе я бы его не размещал здесь.
Может, если добавить соответствующую функцию.
Ответить | Ответить с цитатой | Цитировать
# vadim 06.09.2013 13:59
Так что с приемом более одного байта? У кого то получилось?
Ответить | Ответить с цитатой | Цитировать
# JoJo 06.09.2013 16:04
Тебе же три раза ответили:

1Цитата:
Такой функции там нет. Нужно добавлять.
2Цитата:
Думаю да, но я не пробовал. По хорошему, нужно добавить туда кольцевой буфер и сделать прием и передачу через него.
3Цитата:
Может, если добавить соответствующую функцию.
Ответить | Ответить с цитатой | Цитировать
# vadim 06.09.2013 19:16
Я теперь вообще не пойму смысл такого софтового UARTA в таком исполнении, разве что передать пару байт. Короче UART кастрат, который ещё нужно доводить до ума.
Мне кажет пакетная передача и прием данных это должны были быть основные функции в реализации софтового UART . Да жаль что зря потратил время, нужно было сразу МК с двумя железными UART закладывать в проект. Не доглядел я что тут проблемы с пакетным приемом, сам виноват.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 06.09.2013 20:07
Надо было внимательно читать описание. В пользовательски х функциях есть только функция передачи строки, приема, а точнее чтения строки нет. В чем проблема допилить код самому? Основной функционал реализован. Принимает он в кольцевой буфер (я про это забыл, потому что не притрагивался к этому коду давно). Добавь функцию чтобы считывать из этого буфера данные в требуемую строку.

Например такая может быть функция
Код:
void SUART_GetStr(char *buf, uint8_t size)
{
uint8_t i;

/*копируем size - 1 символов*/
for(i = 0; i < size - 1; i++){
buf[ i ] = SUART_GetChar();
}
/*добавляем конец строки*/
buf[ i ] = 0;
}
Ответить | Ответить с цитатой | Цитировать
# Pashgan 06.09.2013 21:10
Вот эту строчку только поправь #define RX_NUM_OF_BITS 8 и должно заработать. Этот косяк только что нашел.
Я только что проверил код в железяке. У меня ловит строки на скорости 38400.
Ответить | Ответить с цитатой | Цитировать
# vadim 07.09.2013 05:40
Да я и так считывал из кольцевого буфера, это я сделал, проблема в том что в самом буфере только первый принятый байт из пакета нормальный,оста льное каша.

Цитирую Pashgan:
Вот эту строчку только поправь #define RX_NUM_OF_BITS 8 и должно заработать.


А где это строка находится? В хидере? короче у меня в старых исходниках её вроде нигде нет и этот дефайн нигде не используется.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 07.09.2013 06:12
Новые исходники скачай. В сишном файле эта строчка. Из-за нее и каша в остальных символах.
Ответить | Ответить с цитатой | Цитировать
# vadim 07.09.2013 06:30
Паша но не компилируются новые исходники в CV 1.24.8 . Открываю проект в CV , нажимаю компиляцию, на что выпадает сообщение -many error. У тебя какой CV ? Ты пробовал собрать этот проект в нем ?
Ответить | Ответить с цитатой | Цитировать
# Pashgan 07.09.2013 06:59
Проект для CV 2.04. Но думаю для старой версии его тоже можно переделать.
Ответить | Ответить с цитатой | Цитировать
# vadim 07.09.2013 17:09
А #define TX_NUM_OF_BITS 10 , тоже менять на 8 ? Или только #define RX_NUM_OF_BITS 8
Ответить | Ответить с цитатой | Цитировать
# Pashgan 08.09.2013 06:57
Нет, только RX_NUM_OF_BITS.
Ответить | Ответить с цитатой | Цитировать
# vadim 10.09.2013 06:17
Короче,разобрал ся,все работает,но есть одно но, иногда глючит прием данных, из 20 принятых пакетов ,один битый, у меня скорость 9600, хочу попробовать 4800, для этого нужно только сменить скорость в хидере или нужно ещё менять переделитель? И даст ли это что то? Будет ли точней работать софтовый UART на скорости 4800 чем на 9600?
Ответить | Ответить с цитатой | Цитировать
# Pashgan 10.09.2013 07:17
Это зависит от используемого кварца. Поменяй скорость. Если появятся предупреждения, поменяй предделитель. Не знаю, будет ли он точнее работать. Если дело не во внутренних багах, то это зависит от ошибки между задаваемой скоростью и реальной.
Ответить | Ответить с цитатой | Цитировать
# vadim 10.09.2013 19:18
Вот это баг в исходниках софтового UART!!! Я два дня просидел над своим кодом не понимая почему иногда приходит битый пакет данных, уже перелопатил весь свой код , поставил кучу контрольных условий, изменил топологию платы, и когда у меня уже придраться было не к чему, решил глянуть исходники софтового UART , а именно: код приема данных, и тут я был в шоке , а что это за хрень?

rx_data = (uint8_t)intern al_rx_buffer;
if ( rx_data != 0xC2 ){
inbuf[qin] = rx_data;
if ( ++qin >=SUART_BUF_SIZ E ){
qin = 0;
}
}

В функции приема байтов стоит условие на проверку пришедшего байта и если он 0xC2, то он просто пропускается, поэтому у меня и приходили битые пакеты , потому что в них проскакивал байт с таким значением 0xC2, я теперь не пойму а как другие пользовались этими исходниками? Ведь это явный баг влияющий на работу софтового UART. Убрал это строку, тестирую целый день , полет нормальный, софтовый UART работает отлично параллельно с железным . Жаль потраченных двух дней, из за такой ерунды.
Ответить | Ответить с цитатой | Цитировать
# vadim 10.09.2013 19:20
Паша убери в коде это условие. А то ещё кто-то, так как я попадет.
Ответить | Ответить с цитатой | Цитировать
# Pashgan 10.09.2013 19:43
Уберу, когда домой вернусь. Сейчас нет возможности.

Цитата:
Я два дня просидел над своим кодом не понимая почему иногда приходит битый пакет данных, уже перелопатил весь свой код , поставил кучу контрольных условий, изменил топологию платы,
Нормальная ситуация. Сам много раз так попадал и вывел из этого свое правило: "если долго не можешь отловить баг, значит он в какой-то мелочи". Такие штуки, конечно, неприятны, но они повышают инженерное чутье.
Ответить | Ответить с цитатой | Цитировать
# Ozi 21.02.2014 20:13
Привет, Паша! Такой вопрос, этот код универсален? Скажем, к примерау я хочу использовать его в для МК АТмега162 на частоте 8 МГц. Изменяю все настройки частоты, и предделителя в коде соотвественно, вывод: ничего не работает.

Или может надо их как-то по-другому изменять. Помоги, пожалуйста, сижу ломаю, ломаю код, ничего не выходит.
Ответить | Ответить с цитатой | Цитировать
# Enhancer 14.04.2014 20:36
Цитирую Petrov:
Спасибо Pashgan. Подскажи пожалуйста, представленный тобой код позволит принять строку? Дело в том, что я делал программный uart и у меня не получилось допилить свою прошивку до возможности приема строки. На втором символе кристалл затыкался.

Аналогичная проблема, отправка работает отлично, а вот строки принимает неверно, начиная со второго символа начинают приниматься крякозябры. Если отправлять по байту раз в секунду, то все принимается без ошибок. Помогите плиз доделать эту прошивку, чтобы можно было примать строки длинной до 32 байт. Спасибо!
Ответить | Ответить с цитатой | Цитировать
# Enhancer 14.04.2014 21:01
Разобрался, нужно поправить значение кол-во битов на 8 вместо 10, в rx
Ответить | Ответить с цитатой | Цитировать
# Pashgan 16.04.2014 01:35
Да, есть там такой косяк. Не доходят руки проекты поправить.
Ответить | Ответить с цитатой | Цитировать
# Алан 16.05.2014 16:07
Доброго времени суток
На tiny45 cvavr не работал прием, зависала.
поменял размер приемного буффера на 8 ,
вроде отпустило
RX_NUM_OF_BITS поменял на 8
но прием все равно не работает

Может что посоветуете?
Ответить | Ответить с цитатой | Цитировать
# Алан 16.05.2014 16:46
Забыл добавить в протеусе все работает
Ответить | Ответить с цитатой | Цитировать
# dim 19.07.2014 09:17
поделитесь, пожалуйста, проектом на tiny13
Ответить | Ответить с цитатой | Цитировать
# dim 19.07.2014 10:21
вроде все по примеру делаю, но ничего не работает вообще на скорости 9600
Ответить | Ответить с цитатой | Цитировать
# dim 19.07.2014 11:32
только каша, только хардкор
Ответить | Ответить с цитатой | Цитировать
# SashaN 06.08.2014 10:42
Спасибо за отличную библиотеку, для чего
NUM_OF_CYCLES ?
Ответить | Ответить с цитатой | Цитировать
# ave! 02.05.2015 23:08
Рабочий код для STM32F103C8T6 для среды CooCox.
Для STM32F030F4P6 SOFT UART незаменимая штука! Там всего 1 UART.
Тест «BBBBBBBBBBBBBB BBBBBBBBBBBBBBB BBBBBBBBBBBBBBB BBBBBBBBBBBBBBB BBBBBBBBAB» — LED ON на букву "А" в посылке.
http://electronix.ru/forum/index.php?showtopic=127730
Ответить | Ответить с цитатой | Цитировать
# motostep 14.08.2015 18:05
Код:/* Receiver Section */
if (flag_rx_off == FALSE){
if (flag_rx_waiting_for_stop_bit){
if ( --timer_rx_ctr == 0 ){
flag_rx_waiting_for_stop_bit = FALSE;
flag_rx_ready = FALSE;
rx_data = (uint8_t)internal_rx_buffer;
if ( rx_data != 0xC2 ){
inbuf[qin] = rx_data;
if ( ++qin >= SUART_BUF_SIZE ){
qin = 0;
}
}
}
}
else{ // rx_test_busy



не понимаю назначение условия if ( rx_data != 0xC2 ){

если в битовом буфере не 0xC2 то добавляем байт в буфер приема

но при этом при посылке байта 0xC2 он тоже не принимается

как это можно обойти?
Ответить | Ответить с цитатой | Цитировать
# Techno by 18.11.2015 20:38
Пару постов выше было. По ходу просто удалить.
Ответить | Ответить с цитатой | Цитировать
# motostepa 19.11.2015 13:13
Да, действительно удалить. Использую этот код на ATMega8515 с кварцем 7372800 на скорости 14400 кбод/с, совместно с аппаратным уартом и программным SPI, также была добавлена функция SUART_Stop() отключающая программный уарт для освобождения ресурсов контроллера.
Ответить | Ответить с цитатой | Цитировать
# Techno by 20.11.2015 11:40
А я ни как не могу добиться толку. В Протеусе на терминал выводит, а на аппаратный UART ни фига. Первый раз с UARTом работаю) Подскажи какие настройки в этом программном UARTе, 1стоп бит, без проверки чётности?
Ответить | Ответить с цитатой | Цитировать
# motostepa 22.11.2015 16:44
да все так, ты имеешь ввиду что программный работает, а аппаратный нет? Если что смогу помочь мое имя +@mail.ru
Ответить | Ответить с цитатой | Цитировать
# DungeonLords 11.04.2016 17:37
Да исправьте вы уже в примере, Аффтор! Или йаду глотай!

Вот это баг в исходниках софтового UART!!! Я два дня просидел над своим кодом не понимая почему иногда приходит битый пакет данных, уже перелопатил весь свой код , поставил кучу контрольных условий, изменил топологию платы, и когда у меня уже придраться было не к чему, решил глянуть исходники софтового UART , а именно: код приема данных, и тут я был в шоке , а что это за хрень?

rx_data = (uint8_t)intern al_rx_buffer;
if ( rx_data != 0xC2 ){
inbuf[qin] = rx_data;
if ( ++qin >=SUART_BUF_SIZ E ){
qin = 0;
}
}

В функции приема байтов стоит условие на проверку пришедшего байта и если он 0xC2, то он просто пропускается, поэтому у меня и приходили битые пакеты , потому что в них проскакивал байт с таким значением 0xC2, я теперь не пойму а как другие пользовались этими исходниками? Ведь это явный баг влияющий на работу софтового UART. Убрал это строку, тестирую целый день , полет нормальный, софтовый UART работает отлично параллельно с железным . Жаль потраченных двух дней, из за такой ерунды.

vadim
Ответить | Ответить с цитатой | Цитировать
# DungeonLords 12.04.2016 20:18
TIM0_OVF_VECTOR заменить на TIMER0_OVF_vect в Atmel Studio!
Ответить | Ответить с цитатой | Цитировать
# motostep 13.04.2016 18:22
Чуть выше я об этом писал и еще выше об этом же было, тут все на это натыкаются))))

на какой скрости используешь, проц, тактовая? у меня на меге8515, 7.3728МГц быстрее 14400кб/с начинает глючить не стал разбираться оставил как есть - просто надо было завести старый проект.
Ответить | Ответить с цитатой | Цитировать
# alex4 21.04.2016 14:17
Подскажите, пожалуйста, как модифицировать код mega16 для работы на mega328p в среде CodeVision?
Ответить | Ответить с цитатой | Цитировать
# motostepa 28.04.2016 15:51
Если проект не сложный - то логично поменять тип контроллера в настройках проекта и попытаться скомпилировать, а затем подправлять имена регистров и прерываний на которые будет ругаться компилятор.
Ответить | Ответить с цитатой | Цитировать
# Александр13 28.08.2016 10:57
Помогите, хочу использовать блок передачи в переключающемся режиме (передавать на несколько выходов). На одном порту получается, ТХ_PIN объявил вот так:
uint8_t TX_PIN;

А сделать так же с TX_PORTX, TX_DDRX не получается...

Помогите, как правильно это реализовать
Ответить | Ответить с цитатой | Цитировать
# SERQ 28.10.2016 09:13
Не получилось у меня запустить этот код, поэтому предлагаю свой, он очень короткий и рабочий, проверено. Пожалуйста скажите что в нем не так.
https://cloud.mail.ru/public/ND4D/s1S89iXp1
Ответить | Ответить с цитатой | Цитировать
# SERQ 28.10.2016 09:26
Забыл сказать код для ATMEGA8, для других камней могут быть другие названия регистров.
Ответить | Ответить с цитатой | Цитировать

Добавить комментарий

Защитный код
Обновить