Обсуждаем контроллеры компании Atmel.
Ответить

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб ноя 20, 2021 18:50:00

Код:
char str[] = "\0";

массив размером в 2 символа, инициализирован двумя 0-ми.


Код:
char *str = "\0";

Указателю str присваивается символьное значение. Как минимум, должно быть предупреждение.

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб ноя 20, 2021 19:17:27

Указателю str присваивается символьное значение. Как минимум, должно быть предупреждение.

Тут тоже?
Код:
void foo(const char* s) {}

foo("bar");

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт ноя 26, 2021 21:16:42

есть три типа прерываний по UART
1) прием завершен
2)передача завершена
3)регистр данных передатчика пуст
какая разница между последними двумя ?

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт ноя 26, 2021 22:52:21

передача завершена - когда данные ушли по физическим линиям
регистр пуст - значит, можно записать новый байт на передачу, но предыдущий еще до конца не отправился.

передатчик буфферизирован, т.е. там как бы очередь из 2 (или более) регистров, из которых "виден" программисту только первый - когда он пуст, в него можно записывать новое. а непосредственно в линию выдаются данные из самого последнего, сдвигового регистра.

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт ноя 26, 2021 22:56:05

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

Про предыдущий тут лишнее.

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб ноя 27, 2021 10:20:39

ну, в общем, согласен: входной регистр останется пустым и после ухода текущего передаваемого байта...

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб ноя 27, 2021 10:30:20

передача завершена - когда данные ушли по физическим линиям
регистр пуст - значит, можно записать новый байт на передачу, но предыдущий еще до конца не отправился.


в каких случаях нужно использовать ПЕРЕДАЧА ЗАВЕРШЕНА, а в каких РЕГИСТР ДАННЫХ ПЕРЕДАТЧИКА ПУСТ ?
почему тогда просто не оставили режим РЕГИСТР ДАННЫХ ПЕРЕДАТЧИКА ПУСТ ? как я понимаю он шустрее

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб ноя 27, 2021 11:05:15

когда ты прочитаешь принятый байт из регистра данных, то он тоже станет пуст.
а потом в прерывании по пустому регистру ты начнешь гадать, от чего он пуст - по окончании передачи или по окончании приема.
лично я использую прерывание "передача завершена" и там посылаю следующий байт на передачу.

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб ноя 27, 2021 12:17:06

в каких случаях нужно использовать ПЕРЕДАЧА ЗАВЕРШЕНА
Для управления направлением потока данных: например, для выключения передатчика или управления RS-485. Отключать передачу следует именно по факту завершения передачи последнего байта, а не по факту вычитывания его из регистра. Иначе пакет окажется обрезан сзади.

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб ноя 27, 2021 14:03:28

mickbell, а разве кто-то говорил, что отключать передачу надо посреди телеграммы?

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб ноя 27, 2021 14:42:37

написал тестовую программу
Код:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define BAUD_RATE 2400L

unsigned char ch[2] = "A";

void UART0_Init(void) {

   UBRR0 = (F_CPU + 4 * BAUD_RATE) / (8 * BAUD_RATE) - 1; // если с кварцем

   UCSR0A = 1 << U2X0; // удвоение скорости обмена( предделитель уменьшается с 16 до 8)

   UCSR0B = 1 << TXEN0 |  // разрешение передачи
          1 << TXCIE0;  // разрешение прерывания по завершению передачи
   UCSR0C = 1 << UCSZ00 | 1 << UCSZ01 | // определение размера слова данных в 8 бит
          1 << USBS0;   // передатчик посылает 2 СТОП-бита
}


void uart_send_char(unsigned char *ch){

   while (! (UCSR0A & _BV(UDRE0)) );  // Wait for empty transmit buffer
   UDR0 = *ch;
}

int main(void) {

UART0_Init();

sei (); // Global enable interrupts

while(1){

   uart_send_char(ch);

}

}


подключил терминал
Изображение Изображение

как вычислить почему в терменале нет переданных с мк данных ?

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб ноя 27, 2021 15:10:00

mickbell, а разве кто-то говорил, что отключать передачу надо посреди телеграммы?
Отключать передачу надо сразу же (!) после отправки последнего стоп-бита. Уточняю: по окончании передачи этого бита. Осталось понять, каким образом узнать, что этот самый момент таки случился.

Добавлено after 6 minutes 1 second:
как вычислить почему в терменале нет переданных с мк данных ?
Прежде всего, осциллографом посмотреть, что делается на линии TXD (со стороны МК) - RXD (со стороны компа): есть там сигнал или нет. Затем посмотреть, какова длительность передачи бита, и сравнить с заявленной скоростью, возможно, они не соответствуют. Если всё правильно, то надо подать на комп сигнал с другого источника - возможно, порт помер.

Re: Нескольно простых вопросов о программировании AVR на Си.

Вс ноя 28, 2021 16:51:43

на просторах ютуба нашел максимально упрощенный вариант работы передатчика USART
https://www.youtube.com/watch?v=3_omxGI ... nHardDrive
может кому и пригодится :tea:
Код:
#include <avr/io.h>
#include <util/delay.h>


#define F_CPU 16000000
#define BAUD 9600
#define BRC ((F_CPU/16/BAUD)-1) // baud rate calculation


int main(void) {

UBRR0H = (BRC >> 8);
UBRR0L = BRC;


UCSR0B = _BV(TXEN0); // разрешение работы передачика USART
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); // определение размера слова данных в 8 бит

while(1){

   UDR0 = 'W'; // инициализация передачи
   _delay_ms(100);

}

}



Posted after 4 minutes 24 seconds:
на основе приобретенных знаний написал свою ф-цию передачи данных
прошу подсказать и поправить если можна это реализовать проще :tea:
Код:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

//#define F_CPU 16000000
#define BAUD 9600
#define BRC ((F_CPU/16/BAUD)-1) // baud rate calculation
#define TX_BUFFER_SIZE 128


#define enable_interrupt_when_data_register_USART_is_empty   UCSR0B |=  _BV(UDRIE0)
#define disable_interrupt_when_data_register_USART_is_empty  UCSR0B &= ~(1 << UDRIE0)

char TX_BUFFER[TX_BUFFER_SIZE] = " String №1 \n\r";
//char *p_str = " String №2 \n\r";

char *p;



ISR (USART0_TX_vect){// передача закончена

}

ISR (USART0_UDRE_vect){ // регистр данных пуст

   if (*p == '\0'){
      disable_interrupt_when_data_register_USART_is_empty;
   } else {
      UDR0 = *p;
      p++;
   }

}

void uart_send_string(char *s){

   if(bit_is_clear(UCSR0A,TXC0)){ // если предыдущая передача закончена
       p = s;
       UDR0 = *p;
       p++;
       enable_interrupt_when_data_register_USART_is_empty;
   }

}


int main(void) {

DDRB |= _BV(7);

UBRR0H = (BRC >> 8);
UBRR0L = BRC;
//UBRR0 = BRC ;

UCSR0B =  _BV(TXEN0)| // разрешение работы передачика USART
       _BV(TXCIE0); // разрешение прерывания по завершению передачи


UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); // определение размера слова данных в 8 бит

sei (); // Global enable interrupts

while(1){

   uart_send_string(TX_BUFFER);
   _delay_ms(1000);


}

}

Re: Нескольно простых вопросов о программировании AVR на Си.

Вс ноя 28, 2021 19:25:56

включаю зануду.

FreshMan писал(а):void uart_send_string(char *s){

   if(bit_is_clear(UCSR0A,TXC0)){ // если предыдущая передача закончена
       p = s;
       UDR0 = *p;
       p++;
       enable_interrupt_when_data_register_USART_is_empty;
   }

}
а если предыдущая передача не закончена, что тогда? _delay_ms(1000) для надежности? и зачем тогда огород с передачей по прерываниям, если все равно ждать время?

выключаю зануду.

лично я, хоть меня и критиковали не раз за такой подход, в исключительно редких случаях реализовывал передачу по прерываниям, в основном меня всегда удовлетворяет передача по тупому ожиданию:
Код:
void send_char(c){
  while_bit_is_set(UCSR0A, UDRE);
  UDR0 = c;
}

void send_str(char *s){
  while(*s) send_char(s++);
}
тем более, что подобный принцип прекрасно поддерживается системными функциями printf, использовать которые для вывода на компьютерную консоль - милое дело! и практически весь UNIX вырос из именно такого, блокирующего printf...


а вот прием чаще всего удобнее именно по прерыванию. для меня лично, конечно...

Re: Нескольно простых вопросов о программировании AVR на Си.

Вс ноя 28, 2021 19:49:26

включаю зануду.

FreshMan писал(а):void uart_send_string(char *s){

   if(bit_is_clear(UCSR0A,TXC0)){ // если предыдущая передача закончена
       p = s;
       UDR0 = *p;
       p++;
       enable_interrupt_when_data_register_USART_is_empty;
   }

}
а если предыдущая передача не закончена, что тогда? _delay_ms(1000) для надежности? и зачем тогда огород с передачей по прерываниям,


относительно _delay_ms(1000) , я его вставил специально чтобы вывод на терминал был медленным, в реальном проэкте такого конечно же не будет :))
относительно законченности предыдущей задачи: мне представляется, изходя из своего опыта, что было бы правильней не начинать новую передачу пока старая не закончена. Допустим у нас сработали два внешние прерывания с периодичностью в 5мс, и на каждое из них мне нужно как-то отреагировать, допустим послать по юарту 2/3 книги война и мир, это пример явно зафантазированный, но как говорится чем ярче краски тем красивее картинка, так вот исходя из данного примера сообщение второго прерывания нужно бы поставить в очередь пока инфа с первого не передастся, а потом уже чтобы автоматом запустилось второе.
Вот такое мое видение, допускаю что можна проще.
Интересует сам принцип, насколько он правильный ? :roll:

Posted after 5 minutes 24 seconds:
включаю зануду.

тем более, что подобный принцип прекрасно поддерживается системными функциями printf, использовать которые для вывода на компьютерную консоль - милое дело! .

а можна по подробней об этом ?

Re: Нескольно простых вопросов о программировании AVR на Си.

Вс ноя 28, 2021 22:06:28

FreshMan писал(а):было бы правильней не начинать новую передачу пока старая не закончена.
ну так и где это условие у вас? у вас, если флажок пустоты буфера не установлен, функция тупо ничего не сделает, а вызвавший её код никак об этом не узнает...
FreshMan писал(а):а можна по подробней об этом ?
да уж писал много раз... вот тут, например: https://simple-devices.ru/articles/7-so ... omment-392 (там, после смены владельца сайта, порушились врезки кода, но, если напрячься, все будет понятно)

Re: Нескольно простых вопросов о программировании AVR на Си.

Пн ноя 29, 2021 11:52:22

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

Но ведь по прерываниям удобнее. Сказал камню "выведи мне там Хелло-ворлд" и занимаешься своими делами, потом время от времени спрашиваешь сколько там байтов пришло в ответ (может и ноль).
Я не представляю как подход на задержках встраивать в конечный автомат.

Добавлено after 1 minute 55 seconds:
тем более, что подобный принцип прекрасно поддерживается системными функциями printf, использовать которые для вывода на компьютерную консоль - милое дело! и практически весь UNIX вырос из именно такого, блокирующего printf...
В UNIX изначально была многозадачность, то есть пока интерактивный поток ждет пользователя, демоны вполне себе выполняются.

Re: Нескольно простых вопросов о программировании AVR на Си.

Пн ноя 29, 2021 19:38:36

COKPOWEHEU писал(а):Но ведь по прерываниям удобнее.
удобнее, как проще. конечный автомат написать - это думать надо... а так - не надо :)
COKPOWEHEU писал(а):и занимаешься своими делами
это когда дел много...
COKPOWEHEU писал(а):то есть пока интерактивный поток ждет пользователя, демоны вполне себе выполняются
так в МК то же самое. просто для меня приоритеты расставлены так: то, что должно делаться быстро, делается по прерываниям, а то, что может и подождать - в основном цикле. отсюда прием по прерываниям в фоне, а вывод - без прерываний в цикле.

Re: Нескольно простых вопросов о программировании AVR на Си.

Пн ноя 29, 2021 21:33:23

удобнее, как проще. конечный автомат написать - это думать надо... а так - не надо :)
Э-э-э... Вы что, работу с UART каждый раз с нуля пишете? А если кольцевой буфер и прерывания уже написаны, подключение ничем не отличается от работы на задержках.

Re: Нескольно простых вопросов о программировании AVR на Си.

Пн ноя 29, 2021 22:38:19

COKPOWEHEU писал(а):А если кольцевой буфер и прерывания уже написаны, подключение ничем не отличается от работы на задержках.
тогда, пожалуйста, покажите, как просто кольцевой буфер с прерываниями скрестить с prntf?
Ответить