Программный 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 под любой другой камень.

Файлы

Comments   

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


для мега16
# Pashgan 2013-09-06 11:17
Только что скачал SUART- Mega16-CV.rar и проверил. Там архив для Code Vision AVR.
# vadim 2013-09-06 11:51
так а что на счет приема строки на скорости 9600? эта проблема решаема или нет? спасибо за оперативный ответ .
# Pashgan 2013-09-06 12:01
Думаю да, но я не пробовал. По хорошему, нужно добавить туда кольцевой буфер и сделать прием и передачу через него.
# vadim 2013-09-06 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 2013-09-06 12:03
Просто забыл стереть это. Этот файл для всех компиляторов одинаковый, благодаря compiler_3.h.
# vadim 2013-09-06 12:21
А как быть с этим
обработчик прерывания в СV
interrupt [TIM0_OVF] void tim0_ovf(void)

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

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

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

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

Например такая может быть функция
Code:
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 2013-09-06 21:10
Вот эту строчку только поправь #define RX_NUM_OF_BITS 8 и должно заработать. Этот косяк только что нашел.
Я только что проверил код в железяке. У меня ловит строки на скорости 38400.
# vadim 2013-09-07 05:40
Да я и так считывал из кольцевого буфера, это я сделал, проблема в том что в самом буфере только первый принятый байт из пакета нормальный,оста льное каша.

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


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

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

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

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

Может что посоветуете?
# Алан 2014-05-16 16:46
Забыл добавить в протеусе все работает
# dim 2014-07-19 09:17
поделитесь, пожалуйста, проектом на tiny13
# dim 2014-07-19 10:21
вроде все по примеру делаю, но ничего не работает вообще на скорости 9600
# dim 2014-07-19 11:32
только каша, только хардкор
# SashaN 2014-08-06 10:42
Спасибо за отличную библиотеку, для чего
NUM_OF_CYCLES ?
# ave! 2015-05-02 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 2015-08-14 18:05
Code:/* 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 2015-11-18 20:38
Пару постов выше было. По ходу просто удалить.
# motostepa 2015-11-19 13:13
Да, действительно удалить. Использую этот код на ATMega8515 с кварцем 7372800 на скорости 14400 кбод/с, совместно с аппаратным уартом и программным SPI, также была добавлена функция SUART_Stop() отключающая программный уарт для освобождения ресурсов контроллера.
# Techno by 2015-11-20 11:40
А я ни как не могу добиться толку. В Протеусе на терминал выводит, а на аппаратный UART ни фига. Первый раз с UARTом работаю) Подскажи какие настройки в этом программном UARTе, 1стоп бит, без проверки чётности?
# motostepa 2015-11-22 16:44
да все так, ты имеешь ввиду что программный работает, а аппаратный нет? Если что смогу помочь мое имя +@mail.ru
# DungeonLords 2016-04-11 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 2016-04-12 20:18
TIM0_OVF_VECTOR заменить на TIMER0_OVF_vect в Atmel Studio!
# motostep 2016-04-13 18:22
Чуть выше я об этом писал и еще выше об этом же было, тут все на это натыкаются))))

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

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

Помогите, как правильно это реализовать
# SERQ 2016-10-28 09:13
Не получилось у меня запустить этот код, поэтому предлагаю свой, он очень короткий и рабочий, проверено. Пожалуйста скажите что в нем не так.
https://cloud.mail.ru/public/ND4D/s1S89iXp1
# SERQ 2016-10-28 09:26
Забыл сказать код для ATMEGA8, для других камней могут быть другие названия регистров.
# iz 2017-08-24 20:23
Спасибо большое!

У вас недостаточно прав для комментирования.