Например TDA7294

Форум РадиоКот • Просмотр темы - WinAvr в вопросах и ответах
Форум РадиоКот
Здесь можно немножко помяукать :)





Текущее время: Вт июн 24, 2025 22:05:07

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 2195 ]     ... , , , 61, , , ...  
Автор Сообщение
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Пн сен 03, 2012 21:07:24 
Поставщик валерьянки для Кота
Аватар пользователя

Карма: 12
Рейтинг сообщений: 67
Зарегистрирован: Пт авг 27, 2010 05:57:06
Сообщений: 2482
Откуда: Тюмень
Рейтинг сообщения: 0
Про магические числа согласен, и еще хочу добавить насчет этого же отдела кода добавлю свои комментарии
Код:
 if (queueC>50)//Если колличество символов массива больше 50, то...
        {
            queueC = 50;//счетчик символов в массиве равен максимальному значению 50
        }
        queue[queueC++] = *s++; //И тут же прибавляем к 50 единицу??????

тогда уж сделать тут так:
если queueC 50или больше то queueC= 50,
иначе помещаем в буфер.

Кстати зачем помещать в буфер?Если буфер, тогда бы и прерывания применить, а то сначала копировать в буфер опять как то нескладно получается.Зачем тогда нам указатель, если все равно копию делаем?
Делать нужно через прерывания передачу и тогда комментарий к функции будет иметь под собой законное основание.Раз функция помещения в буфер, зачем она передает? :dont_know:

_________________
В поисках истины человек развивается.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Пн сен 03, 2012 21:30:59 
Встал на лапы
Аватар пользователя

Зарегистрирован: Чт май 03, 2012 06:27:23
Сообщений: 116
Откуда: Челябинск
Рейтинг сообщения: 0
Я родил это уровнение:
Код:
if (queueC>50)//Если колличество символов массива больше 50, то...
        {
            queueC = 50;//счетчик символов в массиве равен максимальному значению 50
        }

так как не знаю как выйти из этого цикла при размере массива >50:
Код:
 while (*s)

при достижении queueC = 50. У меня получалось, что 49 символов будет нормальными а пятедисятый будет самым последним символом из массива который больше 50. Я на симуляторе проверял работоспособность этого уровнения, прежде чем выкладывать свой исходный код на форум. Хоть и написанно коряво, но у меня массив больше 50 символов не будет. Покрайней мере в симуляторе все отработало.
Я просто многого не знаю, и при написании программ использую синтаксис, который прочитал в учебниках или же увидел на просторах инета. :)
PS: По поводу учебника Тэда Джонса, я тут его щас с помощью промта перевел, читаю. Тяжко. :shock:

_________________
Кот должен прожить жизнь без сожаления.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Пн сен 03, 2012 22:20:05 
Поставщик валерьянки для Кота
Аватар пользователя

Карма: 12
Рейтинг сообщений: 67
Зарегистрирован: Пт авг 27, 2010 05:57:06
Сообщений: 2482
Откуда: Тюмень
Рейтинг сообщения: 0
лучше авто переводчиком не пользоваться, он так все слова переставит, что весь смысл теряется.Значений слов много, автоматически невозможно точно подобрать то, что нужно.

_________________
В поисках истины человек развивается.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Пн сен 03, 2012 23:45:39 
Опытный кот
Аватар пользователя

Карма: 8
Рейтинг сообщений: 65
Зарегистрирован: Пн янв 10, 2011 03:06:36
Сообщений: 736
Откуда: Ростов-на-Дону
Рейтинг сообщения: 0
DruidCat писал(а):
не знаю как выйти из этого цикла при размере массива >50
Варианты:

1.
Код:
 while (*s && (queueC < BUFF_SIZE))

2.
Код:
    while (*s)
    {
        if (queueC >= BUFF_SIZE)
        {
            break;
        }
        queue[queueC++] = *s++;   //Просматриваем строку и помещаем в очередь символы
    }
Первый вариант предпочтительнее, поскольку break несколько сродни goto и с трудом вписывается в структурное программирование. Но иногда бывает, что с ними проще.

DruidCat писал(а):
Я на симуляторе проверял работоспособность этого уровнения, прежде чем выкладывать свой исходный код на форум.
Не довод. В данном случае переменных мало, и вполне вероятно, что в RAM после буферного массив идет незадействованная область. Ее порча просто незаметна. Но в нынешнем виде программа не слишком функциональна, скорее демо для подпрограммы вывода в UART. Если же этот фрагмент будет использован в реальной программе и после буфера окажутся другие переменные, можно нарваться на загадочное поведение.

Недавно мне попалась книга Lisa Simone, If I Only Changed the Software, Why is the Phone on Fire? Embedded Debugging Methods Revealed. Technical Mysteries for Engineers. Там в первой же главе описывается подобная проблема и методы ее диагностики. Вообще довольно толковая книга, рекомендую.

DruidCat писал(а):
Покрайней мере в симуляторе все отработало.
Совершенно не довод. Дело вовсе не в неадекватности симулятора, их как раз я очень уважаю. Просто, раз уж взялись серьезно за программирование, привыкайте, что в этой среде фраза "вот видите, включил - все работает" совершенно ничего не значит. Могу рассказать очень поучительную историю, как на одном военном заводе в самый неподходящий момент крупно облажалась самописная программа, которая до этого весьма интенсивно проработала 10 лет при ежедневном использовании и не выдала ни единого сбоя, тем самым усыпив бдительность разработчиков.

DruidCat писал(а):
PS: По поводу учебника Тэда Джонса, я тут его щас с помощью промта перевел, читаю. Тяжко. :shock:
Промт - совершенно негодный продукт (впрочем, годных я в области машинного перевода не встречал). Он больше сбивает с толку, чем помогает. Лучше вооружитесь хорошим словарем (например, тот же Lingvo либо онлайновый словарь в Yandex), а совсем непонятные фразы спрашивайте, поможем.

_________________
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle


Вернуться наверх
 
В продаже новые LED-драйверы XLC компании MEAN WELL с диммингом нового поколения

Компания MEAN WELL пополнила ассортимент своей широкой линейки светодиодных драйверов новым семейством XLC для внутреннего освещения. Главное отличие – поддержка широкого спектра проводных и беспроводных технологий диммирования. Новинки представлены в MEANWELL.market моделями с мощностями 25 Вт, 40 Вт и 60 Вт. В линейке есть модели, работающие как в режиме стабилизации тока (СС), так и в режиме стабилизации напряжения (CV) значением 12, 24 и 48 В.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Вт сен 04, 2012 16:02:50 
Встал на лапы
Аватар пользователя

Зарегистрирован: Чт май 03, 2012 06:27:23
Сообщений: 116
Откуда: Челябинск
Рейтинг сообщения: 0
Ура, это решение:
Код:
while (*s && (queueC < BUFF_SIZE))


Я что то подобное до этого пытался написать, глянул в учебнике Шпака, что "или" обозначается || и написал вот так

Код:
while (*s || (queueC < BUFF_SIZE))


И у меня ничего не заработало, пришлось родить вот это: :))

Код:
if (queueC>50)//Если колличество символов массива больше 50, то...
        {
            queueC = 50;//счетчик символов в массиве равен максимальному значению 50
        }


По поводу замечаний, так я им очень рад, я ведь учусь и не варюсь в собственном соку, я наоборот у вас пытаюсь учиться правильно писать исходный код, и все ваши советы беру себе на вооружение как стандарт поведения. :beer:
Промт действительно коряво переводит, пришлось все читать в двух окошках, смотря на два языка одновременно. Книжка толковая, я её всю не прочитал, но половину точно прочел кое как, очень много для себя узнал нового. Мне там понравилось, что там всё разжёвывают, в рот ложат, осталось только проглотить.
PS: Я думал что break работает только в связке switch-case, а оказывается нет. Блин. :(

_________________
Кот должен прожить жизнь без сожаления.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Вт сен 04, 2012 19:26:29 
Поставщик валерьянки для Кота
Аватар пользователя

Карма: 12
Рейтинг сообщений: 67
Зарегистрирован: Пт авг 27, 2010 05:57:06
Сообщений: 2482
Откуда: Тюмень
Рейтинг сообщения: 0
break работает везде, откуда есть выход, соответственно можно думая что будет выход из того, что нужно, он выйдет из одного уровня, а из второго нет.
Например поместив брейк в свитч уже нельзя выйти из цикла, в котором этот свитч находится.

_________________
В поисках истины человек развивается.


Вернуться наверх
 
Распродажа паяльного оборудования ATTEN!
Паяльные станции, паяльники и аксессуары по самой выгодной цене.

По промокоду radiokot скидка 10%
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Вт сен 04, 2012 22:49:45 
Опытный кот
Аватар пользователя

Карма: 8
Рейтинг сообщений: 65
Зарегистрирован: Пн янв 10, 2011 03:06:36
Сообщений: 736
Откуда: Ростов-на-Дону
Рейтинг сообщения: 0
DruidCat писал(а):
глянул в учебнике Шпака
"Шпак не нужен" (С).

Попробуйте лучше книгу: M. Уэйт, С. Прата, Д. Мартин. Язык Си. Руководство для начинающих. Кликнул, вроде ссылки целые.

Книга написана еще в старые добрые времена, до эпохи букварей серии "освой самостоятельно за 15 минут". Конечно, ей почти четверть века, и более поздних веяний в стиле C99 и далее вы в ней не найдете (впрочем, с таким же успехом не найдете их и в книжках от шпаков). Зато материал изложен последовательно, и по прочтении пробелов не должно остаться. Я в конце 80-х учил по ней своих студентов.

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

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

_________________
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle


Последний раз редактировалось Goldsmith Ср сен 05, 2012 11:02:09, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Ср сен 05, 2012 07:32:40 
Вымогатель припоя

Зарегистрирован: Ср янв 05, 2011 10:03:18
Сообщений: 581
Рейтинг сообщения: 0
Goldsmith писал(а):
Только добрый совет: не торопитесь брать все наши советы за стандарт. Советчики разные попадаются... Побольше сомневайтесь и все поверяйте логикой, в данном случае это только на пользу.
+100500

_________________
С уважением,
Виктор.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Ср сен 05, 2012 19:24:27 
Встал на лапы
Аватар пользователя

Зарегистрирован: Чт май 03, 2012 06:27:23
Сообщений: 116
Откуда: Челябинск
Рейтинг сообщения: 0
Почитал тут один учебник и нашел функцию strlen, и решил избавиться от указателей в своём коде. И все ваши замечания я учёл.
Во: :)))

Код:
//********************************************************************************
//
// Файл       : send_usart.h
//
// Автор      : DruidCat
//
// МК         : ATMega8L
//
// Компилятор : WinAVR
//
// Назначение : Выводим строку и число по USART через универсальную функцию
//
// Дата       : 05.09.2012
//
// Версия     : 1.6
//
//********************************************************************************

#ifndef SEND_USART_H
#define SEND_USART_H

#include <avr/io.h>
#include <string.h>      //Вызов функции strlen
#define F_CPU 8000000UL      //Частота МК
#define USART_SPEED 9600   //Скорость USART желаемая
#define BAUD ((F_CPU/(USART_SPEED*16UL)) - 1)   //Формула расчета БОД

//********************************************************************************

//прототипы функций

void INIT_USART (void);      //Функция настройка USART
void SEND_USART (char STRING[]);   //Функция вывода символов.

#endif


Код:
//********************************************************************************
//
// Файл       : send_usart.c
//
// Автор      : DruidCat
//
// МК         : ATMega8L
//
// Компилятор : WinAVR
//
// Назначение : Выводим строку и число по USART через универсальную функцию
//
// Дата       : 05.09.2012
//
// Версия     : 1.6
//
//********************************************************************************

#include "send_usart.h"

void INIT_USART (void)      //Функция настройка USART
{
  UBRRH = (unsigned char) (BAUD >> 8);   //Скорость передач
  UBRRL = (unsigned char) BAUD;   //Скорость передач
  UCSRB = (0 << RXCIE) | (0 << TXCIE) | (0 << RXEN) | (1 << TXEN);   //Разрешение передачи
  UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);   //размер слова 8 разрядов
}

void SEND_USART (char STRING[])   //Функция вывода символов
{
  int N = strlen (STRING);   //Подсчитываем колличество символов в массиве
  for (int i = 0; i != N; i++)   //Цикл вывода строки по USART
    {
      while ((UCSRA & (1 << UDRE)) == 0);   //Пауза, цикл работает пока регистр данных не опустошён
      UDR = STRING[i];      //Выводим посимвольно символы в масиве по USART
      while ((UCSRA & (1 << UDRE)) == 0);   //Пауза, цикл работает пока регистр данных не опустошён
    }
}


Код:
//********************************************************************************
//
// Автор      : DruidCat
//
// МК         : ATMega8L
//
// Компилятор : WinAVR
//
// Назначение : Выводим строку и число по USART через универсальную функцию
//
// Дата       : 05.09.2012
//
// Версия     : 1.6
//
//********************************************************************************
#include <avr/io.h>
#include <stdlib.h>      //Вызов функции itoa, ltoa
#include "send_usart.h"

int main (void) //Главная функция
{
  INIT_USART ();      //Вызываем функцию для настройки USART
  char HIGHT[] = "Высота ";   //Массив символов HIGHT
  long int NUMBERS = 239;   //Число для преобразования NUMBERS

  char *CHAR_NUMBERS;      //указатель CHAR_NUMBERS
  char BUFFER[20];      //Символьный буфер преобразуемого числа
  CHAR_NUMBERS = ltoa (NUMBERS, BUFFER, 10);   //объявляем указатель на массив ltoa

  while (1)         //Бесконечный цикл
    {
      SEND_USART (HIGHT);   //Отсылаем массив HIGHT в функцию SEND_USART
      SEND_USART (CHAR_NUMBERS);   //Отсылаем указатель CHAR_NUMBERS массива ltoa в функцию SEND_USART
      UDR = 0x0A;      //возврата каретки и переноса строки
    }
}


Опять же, проверил работу в симуляторе VMLAB, вроде работает. 8)

PS: У меня на работе "Высота 239" служба автоматизации говорит так "Вроде работает" (1) и "Неведомая херня" (0) :)))


Вложения:
send_usart.h [938 байт]
Скачиваний: 208
send_usart.c [1.26 KiB]
Скачиваний: 424
main.c [1.16 KiB]
Скачиваний: 405

_________________
Кот должен прожить жизнь без сожаления.
Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Ср сен 05, 2012 21:57:08 
Поставщик валерьянки для Кота
Аватар пользователя

Карма: 12
Рейтинг сообщений: 67
Зарегистрирован: Пт авг 27, 2010 05:57:06
Сообщений: 2482
Откуда: Тюмень
Рейтинг сообщения: 0
Вот теперь уже ближе к правде, учитывая то что без прерываний.
Есть примечание не нужно два раза в цикле
Код:
 while ((UCSRA & (<< UDRE)) == 0);  

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

_________________
В поисках истины человек развивается.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Ср сен 05, 2012 22:43:36 
Опытный кот
Аватар пользователя

Карма: 8
Рейтинг сообщений: 65
Зарегистрирован: Пн янв 10, 2011 03:06:36
Сообщений: 736
Откуда: Ростов-на-Дону
Рейтинг сообщения: 0
DruidCat писал(а):
Код:
UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0); //размер слова 8 разрядов
Небольшой совет: в <avr/io.h> определен макрос:
Код:
#define _BV( bit ) (1 << (bit))
С его использованием процитированный фрагмент будет выглядеть так:
Код:
UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);
IMHO выглядит выразительнее.

_________________
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Чт сен 06, 2012 05:05:29 
Встал на лапы
Аватар пользователя

Зарегистрирован: Чт май 03, 2012 06:27:23
Сообщений: 116
Откуда: Челябинск
Рейтинг сообщения: 0
vitalik_1984 писал(а):
Вот теперь уже ближе к правде, учитывая то что без прерываний.
Есть примечание не нужно два раза в цикле
Код:
 while ((UCSRA & (<< UDRE)) == 0);  

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

Я подумал, что буду два раза проверять освобождение буфера передачи для того, чтобы учесть строчки, подобные этой:
Код:
UDR = 0x0A;      //возврата каретки и переноса строки


По поводу _BV, мне не удобно использовать классическую запись в С. Для меня нет наглядность, особенно в таких конструкциях как
Код:
USCRC &=~_BV(URSEL)

мне, как электрику, тяжело это осознать. :cry:
PS: Спасибо мужики за помощь. :beer:

_________________
Кот должен прожить жизнь без сожаления.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Чт сен 06, 2012 09:28:23 
Опытный кот
Аватар пользователя

Карма: 8
Рейтинг сообщений: 65
Зарегистрирован: Пн янв 10, 2011 03:06:36
Сообщений: 736
Откуда: Ростов-на-Дону
Рейтинг сообщения: 0
DruidCat писал(а):
Я подумал, что буду два раза проверять освобождение буфера передачи для того, чтобы учесть строчки, подобные этой:
Код:
UDR = 0x0A;      //возврата каретки и переноса строки
Плохой вариант сразу по нескольким причинам.

1. Управление кареткой можно делать явно при помощи управляющих литер \n и \r, например:
Код:
char singleString[] = "После этой строки будет переход на новую\r\n";
Если нужно просто перейти на другую строку, достаточно вывести "\r\n". Для большинства читающих это гораздо понятнее, чем явный вывод константы в регистр.

Никогда не следует забывать, что исходный текст программы пишется в первую очередь для людей и потому должен наиболее ясно выражать намерения программиста. Компилятор не будет возражать, если мы назовем все переменные и функции a1, a2 и т.д. и запишем программу в одну строку без отступов. Ну а процессору и подавно все равно, ему двоичный код подавай. Поэтому из нескольких возможных вариантов всегда нужно выбирать тот, который понятнее при чтении человеком (Дональд Кнут называет это "literate programming").

2. Если видите, что возникает потребность в выводе на UART не только строк, но и отдельных литер, разбейте SEND_USART на две функции - вывод одной литеры и вывод строки по одной литере. Тогда вместо
Код:
UDR = 0x0A;      //возврата каретки и переноса строки
в программе будет что-то вроде
Код:
uart_sendChar('*');
Второй вариант гораздо ближе к "грамотному программированию" Кнута, поскольку для его понимания читателю не нужно рыться в описании регистров МК, он достаточно красноречиво говорит о своем назначении. Заодно избежите дублирования кода, которое является очень плохим "запахом".

(Попутно небольшая придирка по стилю: не следует использовать имена на верхнем регистре для переменных и функций (вроде SEND_USART); в культуре C устоялась традиция называть таким образом макросы).

3. Очень плохо, когда одновременно несколько модулей программы "знают" об особенностях конкретного оборудования. В Вашей программе UDR упомянут и в send_usart.c, и в main.c. Это плохо, опять же, по нескольким причинам.

Во-первых, в разных моделях МК зачастую сходные по назначению регистры именуются разными мнемониками. Если столкнетесь с этим, придется выискивать и заменять UDR по всей программе.

Во-вторых, требования к программному обеспечению часто меняются, и выживает лишь код, способный быстро и легко адаптироваться к этим изменениям. Например, заказчика заинтересовал Ваш прибор, но через некоторое время он приходит с просьбой: "Давайте добавим LCD и будем выводить данные либо в UART, либо на экран". Опять же, придется переписывать весь код, поскольку аппаратная зависимость раскидана повсюду.

Путь к спасению тут единственный - сосредоточить всю зависимость от оборудования в едином модуле-драйвере. Весь остальной код использует этот драйвер как абстракцию, не вникая в детали его работы. Изменится оборудование - подкорректируйте драйвер. Добавится новое оборудование - напишите новый драйвер для него. Остальной код менять не придется (или почти не придется).

P.S. Только не спешите сразу следовать этим рекомендациям и исправлять программу, не вникнув в их суть.

_________________
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Чт сен 06, 2012 11:14:18 
Опытный кот
Аватар пользователя

Карма: 7
Рейтинг сообщений: 52
Зарегистрирован: Чт дек 31, 2009 19:27:45
Сообщений: 842
Откуда: Бровари, Україна
Рейтинг сообщения: 0
vitalik_1984 писал(а):
Например поместив брейк в свитч уже нельзя выйти из цикла, в котором этот свитч находится.
Иногда удобно смешать с continue, но только switch должен быть в конце цикла.
Код:
for ( ... ) {
    
// получили какие-то данные и их рассматриваем либо
    // сделали действия и анализируем статус
    
switch ( ... ) {
    case ... :
        
// перешли НА закрывающую скобку for,
        // т.е. на третий оператор в for -- for ( ... ; ... ; вот_сюда)
        
continue;
    case ... :
        
// А тут ещё что-то сделали и только потом
        
continue; // перешли НА закрывающую скобку for;
    
case ... :
        
// А тут ещё как-то обработали ошибку
        
break; // перешли ЗА закрывающую скобку switch
    
default:
        break; 
// перешли ЗА закрывающую скобку switch
    
}
    
// тут в принципе может быть общая часть обработки ошибок
    
break; // перешли ЗА закрывающую скобку for

_________________
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Чт сен 06, 2012 11:21:25 
Опытный кот
Аватар пользователя

Карма: 7
Рейтинг сообщений: 52
Зарегистрирован: Чт дек 31, 2009 19:27:45
Сообщений: 842
Откуда: Бровари, Україна
Рейтинг сообщения: 0
Goldsmith писал(а):
Первый вариант предпочтительнее, поскольку break несколько сродни goto и с трудом вписывается в структурное программирование.
Да, несомненно, break и continue это эвфемизмы, предназначенные для того, чтобы в приличном обществе сказать то, что обычно говорят при помощи goto, чтобы все тебя поняли, но чтобы соблюсти приличия.

Goldsmith писал(а):
Но иногда бывает, что с ними проще.
Настолько проще, что даже Вирт, когда делал Модулу, решил, что паскалевский набор циклов слабоват и добавил бесконечный цикл LOOP с возможностью выхода из него в любом месте любое количество раз при помощи оператора EXIT.
А в турбо-паскале ввели Break и Continue как расширение паскаля.

А уж ADA так и вообще имеет «deep level early exit», т.е. break из нескольких охватывающих блоков.
Код:
loop_y : for y in 1..MAXY do
         begin
         loop_x : for x in 1..MAXX do
             begin
                 exit loop_y when object_found(x,y);
             end
         end
вот по этому exit делаем выход аж по цикл, помеченный loop_y

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

Тут бы что-то в духе (детально, естественно, не обдумывалось, так, иногда засыпая)
Код:
for ( ... ) : outer_for { // Этому циклу дали имя outer_for
    for ( ... ) : middle_for {
        for ( ... ) {
            if ( ... ) {
                // вывалиться из всех трёх циклов, но при этом
                // отработать ветви else всех охватывающих циклов
                // в данном примере -- цикла middle_for
                break outer_for;
            }
        }
    } else {
        // Вышли аж из внутреннего цикла, но, "пролетая над Череповцом", зашли сюда
        // сделать завершающие действия для среднего цикла
    }
}
 
(ну не else, так onbreak)
Во многих случаях это позволило бы удобно сделать в С то, что в С++ делается деструкторами и совсем тяжеловесными try/catch.
Но это уже не к C, а свой язык я точно не рожу :-)

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

_________________
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Чт сен 06, 2012 12:10:41 
Встал на лапы
Аватар пользователя

Зарегистрирован: Чт май 03, 2012 06:27:23
Сообщений: 116
Откуда: Челябинск
Рейтинг сообщения: 0
Я когда на ZX Spectrum писал програмки, пользовался go to в Бэйсике :)))

_________________
Кот должен прожить жизнь без сожаления.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Чт сен 06, 2012 22:19:16 
Встал на лапы
Аватар пользователя

Зарегистрирован: Чт май 03, 2012 06:27:23
Сообщений: 116
Откуда: Челябинск
Рейтинг сообщения: 0
Учел все ваши замечания многоуважаемые Коты.
Вот что получилось: 8)

Код:
//********************************************************************************
//
// Файл       : send_usart.h
//
// Автор      : DruidCat
//
// МК         : ATMega8L
//
// Компилятор : WinAVR
//
// Назначение : Выводим строку и число по USART через универсальную функцию
//
// Дата       : 07.09.2012
//
// Версия     : 1.7
//
//********************************************************************************

#ifndef SEND_USART_H
#define SEND_USART_H

#include <avr/io.h>
#include <string.h>      //Вызов функции strlen

//Настройка регистра UCSRB
#define UCSRB_RXCIE 0 //Если 1, то разрешение прерывания по завершению приема по uSART
#define UCSRB_TXCIE 0 //Если 1, то разрешение прерывания по завершении передачи по uSART
#define UCSRB_UDRIE 0 //Если 1, то разрешение прерывания при очистке регистра данных USART
#define UCSRB_RXEN 0 //Если 1, то разрешение приема по USART
#define UCSRB_TXEN 1 //Если 1, то разрешение передачи по USART

//Настройка скорости передачи данных по USART
#define F_CPU 8000000UL      //Частота МК
#define USART_SPEED 9600   //Скорость USART желаемая
#define BAUD ((F_CPU/(USART_SPEED*16UL)) - 1)   //Формула расчета БОД

//********************************************************************************

//прототипы функций

void send_usart (char String[]);   //Функция вывода символов.

#endif /* SEND_USART_H_ */


Код:
//********************************************************************************
//
// Файл       : send_usart.c
//
// Автор      : DruidCat
//
// МК         : ATMega8L
//
// Компилятор : WinAVR
//
// Назначение : Выводим строку и число по USART через универсальную функцию
//
// Дата       : 07.09.2012
//
// Версия     : 1.7
//
//********************************************************************************

#include "send_usart.h"

void send_usart (char String[])   //Функция вывода символов
{
  int N = strlen (String);   //Подсчитываем колличество символов в массиве
  for (int i = 0; i != N; i++)   //Цикл вывода строки по USART
    {
      while ((UCSRA & _BV(UDRE)) == 0);   //Пауза, цикл работает пока регистр данных не опустошён
      UDR = String[i];      //Выводим посимвольно символы в масиве по USART
    }
}

//Вызывать из основного модуля эту функцию не нужно.
__attribute__((naked, section(".init7")))
void init_usart (void)// Функция настройки параметров USART.
{
//Настраиваем скорость передачи по USART
  UBRRH = (unsigned char) (BAUD >> 8);   //Скорость передач
  UBRRL = (unsigned char) BAUD;   //Скорость передач

//Настраиваем регистр UCSRB 
  #if UCSRB_RXCIE == 1
  UCSRB |= _BV(RXCIE);//Разрешение прерывания по завершению приема по uSART
#endif

#if UCSRB_TXCIE == 1
  UCSRB |= _BV(TXCIE);//Разрешение прерывания по завершении передачи по uSART
#endif

#if UCSRB_UDRIE == 1
  UCSRB |= _BV(UDRIE);//Разрешение прерывания при очистке регистра данных USART
#endif

#if UCSRB_RXEN == 1
  UCSRB |= _BV(RXEN);//Разрешение приема по USART
#endif

#if UCSRB_TXEN == 1
  UCSRB |= _BV(TXEN);//Разрешение передачи по USART
#endif

//Настраиваем регистр UCSRC 
  UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);   //размер слова 8 разрядов
}


Код:
//********************************************************************************
//
// Автор      : DruidCat
//
// МК         : ATMega8L
//
// Компилятор : WinAVR
//
// Назначение : Выводим строку и число по USART через универсальную функцию
//
// Дата       : 07.09.2012
//
// Версия     : 1.7
//
//********************************************************************************
#include <avr/io.h>
#include <stdlib.h>      //Вызов функции itoa, ltoa
#include "send_usart.h" //Вызов библиотеки с универсальной функцией вывода символов по USART

int main (void)         //Главная функция
{
  char Hight[] = "Высота ";   //Массив символов Hight
  long int Numbers = 239;   //Число для преобразования Numbers
 
  //Пример пользования функцией ltoa
  char *Char_numbers;      //указатель Char_numbers
  char Buffer[20];      //Символьный буфер преобразуемого числа
  Char_numbers = ltoa (Numbers, Buffer, 10);   //объявляем указатель на массив ltoa

  while (1)         //Бесконечный цикл
    {
      send_usart (Hight);   //Отсылаем массив HIGHT в функцию send_usart
      send_usart (Char_numbers);   //Отсылаем указатель CHAR_NUMBERS массива ltoa в функцию send_usart
      send_usart ("\r\nСпасибо Коты за помощь!\r\n");   //Возврат каретки и пренос строки "БЛАГОДАРНОСТЬ!" возврат каретки и пренос строки
    }
}


Я с макросами дело раньше не имел, поэтому подглядел исходный код у многоуважаемого кота ARV
Код:
__attribute__((naked, section(".init7")))
void init_usart (void)// Функция настройки параметров USART.
{
Определение регистров
}


Я понял что эта функция позволяет определять регистры, а __attribute__((naked, section(".init7"))) позволяет не запускать эту функцию в основной программе. И инициализирует эту функцию. А почему это так работает, я не знаю :(
PS: Проверял работу на симуляторе. Вроде работает. :)))


Вложения:
main.c [1.22 KiB]
Скачиваний: 382
send_usart.c [1.71 KiB]
Скачиваний: 412
send_usart.h [1.33 KiB]
Скачиваний: 425

_________________
Кот должен прожить жизнь без сожаления.
Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Чт сен 06, 2012 22:36:11 
Опытный кот
Аватар пользователя

Карма: 7
Рейтинг сообщений: 52
Зарегистрирован: Чт дек 31, 2009 19:27:45
Сообщений: 842
Откуда: Бровари, Україна
Рейтинг сообщения: 0
DruidCat писал(а):
Код:
//Настраиваем регистр UCSRB 
  #if UCSRB_RXCIE == 1
  UCSRB |= _BV(RXCIE);//Разрешение прерывания по завершению приема по uSART
#endif
#if UCSRB_TXCIE == 1
  UCSRB |= _BV(TXCIE);//Разрешение прерывания по завершении передачи по uSART
#endif
#if UCSRB_UDRIE == 1
  UCSRB |= _BV(UDRIE);//Разрешение прерывания при очистке регистра данных USART
#endif
#if UCSRB_RXEN == 1
  UCSRB |= _BV(RXEN);//Разрешение приема по USART
#endif
#if UCSRB_TXEN == 1
  UCSRB |= _BV(TXEN);//Разрешение передачи по USART
#endif
Тут будет горсть команд sbi. А если написать так:
Код:
    uint8_t ucsrb_val = 0;
#if UCSRB_RXCIE == 1
    ucsrb_val |= _BV(RXCIE);
#endif
#if UCSRB_TXCIE == 1
    ucsrb_val |= _BV(TXCIE);
#endif
#if UCSRB_UDRIE == 1
    ucsrb_val |= _BV(UDRIE);
#endif
#if UCSRB_RXEN == 1
    ucsrb_val |= _BV(RXEN);
#endif
#if UCSRB_TXEN == 1
    ucsrb_val |= _BV(TXEN);
#endif
    UCSRB = ucsrb_val; 
То мало-мальски грамотный оптимизатор соберёт все константы во время компиляции и выдаст в код что-то в духе
Код:
   ldi r24,lo8(-8)
   out 42-32,r24
Т.е. две команды независимо от того, что было нужно -- просто будет меняться константа.
Если в программе будут подниматься только биты TXEN, RXEN, то будет две команды sbi либо тут эти две команды. Размер кода одинаков (при трёх взводимых битах тут уже выигрыш). Но две команды sbi будут выполняться 4 такта, а ldi+out -- два. Впрочем, для начальной инициализации время не так важно.

DruidCat писал(а):
__attribute__((naked, section(".init7"))) позволяет не запускать эту функцию в основной программе. И инициализирует эту функцию. А почему это так работает, я не знаю :(

Секции .init в avr-gcc
А гугол уже неплохо переводит... Когда это только было написано, он перевёл хуже.

_________________
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Пт сен 07, 2012 01:33:15 
Опытный кот
Аватар пользователя

Карма: 8
Рейтинг сообщений: 65
Зарегистрирован: Пн янв 10, 2011 03:06:36
Сообщений: 736
Откуда: Ростов-на-Дону
Рейтинг сообщения: 0
Сначала, как всегда, мелкие придирки (поскольку чужой труд ругать куда легче, чем самому что-то полезное сделать).
DruidCat писал(а):
Код:
//********************************************************************************
// Файл       : send_usart.h
...
// Назначение : Выводим строку и число по USART через универсальную функцию               (1)
...

#include <avr/io.h>                                                                       (4)   
#include <string.h>      //Вызов функции strlen                                           (2)

//Настройка регистра UCSRB                                                                (3)
#define UCSRB_RXCIE 0 //Если 1, то разрешение прерывания по завершению приема по uSART
#define UCSRB_TXCIE 0 //Если 1, то разрешение прерывания по завершении передачи по uSART
#define UCSRB_UDRIE 0 //Если 1, то разрешение прерывания при очистке регистра данных USART
#define UCSRB_RXEN 0 //Если 1, то разрешение приема по USART
#define UCSRB_TXEN 1 //Если 1, то разрешение передачи по USART

//Настройка скорости передачи данных по USART
#define F_CPU 8000000UL      //Частота МК
#define USART_SPEED 9600   //Скорость USART желаемая
#define BAUD ((F_CPU/(USART_SPEED*16UL)) - 1)   //Формула расчета БОД

...
(1) Прекрасная привычка - приводить в начале модуля комментарии, полностью разъясняющие его назначение. Не нужно проводить детективное расследование, чтобы понять, что он делает. (Если еще и отформатировать содержательный комментарий в стиле Doxygen, то ему вообще цены не будет).

Плохая привычка - обманывать в этих комментариях доверчивого читателя. На самом деле в нем нет средств для вывода чисел, только строк. Значит, только о выводе строк и упоминаем. Как Мефистофель справедливо корил Фауста в аналогичном случае, "Ты обещанье дал напрасно".

(2) Лучше не засорять заголовочный файл вложенными заголовками, которые не используются в нем непосредственно. В данном случае таким явно лишним заголовком является <string.h>. Его можно вполне безболезненно убрать. Кому понадобятся функции работы со строками, пусть включает их сам.

(3) Опять же, модулю-клиенту драйвера, который выводит через него данные вовсе не обязательно знать о константах настройки USART вроде тактовой частоты или флага разрешения прерывания по приему. Это тот самый случай, о котором в книге Экклезиаста сказано: "и кто умножает познания, умножает скорбь" (и заодно размер заголовочного файла). Все эти определения вполне уместно вынести непосредственно в тот файл, где они будут использоваться, поскольку никому более они не интересны. Более того, есть соблазн, например, "включить" прерывания от передатчика, переопределив UCSRB_UDRIE, но ни к чему хорошему это не приведет, поскольку прерывания не поддержаны реализацией модуля (хотя из заголовка это никак не видно). А коли так, лучше прятать эти детали поглубже на тот уровень, где они действительно используются.

(4) Заголовок <avr/io.h> тоже не нужен клиентам нашего драйвера, поскольку мы договорились все аппаратно-заависимые детали упрятать в реализацию драйвера.

Теперь в заголовочном файле остается лишь прототип функции
Код:
void send_usart (char String[]);   //Функция вывода символов.
Этого вполне достаточно для клиентов, которые желают выводить строки. Остальное для них явно лишнее.


DruidCat писал(а):
Код:
// Файл       : send_usart.c
...
void send_usart (char String[])   //Функция вывода символов
{
  int N = strlen (String);   //Подсчитываем колличество символов в массиве
  for (int i = 0; i != N; i++)   //Цикл вывода строки по USART
...
Делаем явно лишнюю работу: сначала заставляем функцию strlen перебрать в цикле все литеры в строке, пока не наткнется на завершающий '\0', и подсчитать их количество; затем опять перебираем те же литеры для вывода в USART. Проще было бы выводить их, пока не встретим '\0', а количество литер - опять же "познания, умножающие скорбь":
Код:
for (int i = 0; !String[i]; i++) ...
В принципе мелочь - одна лишняя переменная и десяток-другой микросекунд на лишний вызов библиотечной функции; но, с другой стороны, чем чище код - тем выше его качество.

DruidCat писал(а):
Код:
      while ((UCSRA & _BV(UDRE)) == 0);   //Пауза, цикл работает пока регистр данных не опустошён
1. Вместо (условие == 0) с таким же успехом можно писать (!условие). Второй вариант читабельнее, поскольку конфузливо скрывает факт, что C так и не обзавелся полноценным булевским типом.

2. Вместе с макросом _BV в библиотеке определены также еще несколько полезных макросов для работы с битами. Один из них:
Код:
#define loop_until_bit_is_set( sfr, bit ) do { } while (bit_is_clear(sfr, bit))
ожидает в пустом цикле, пока в регистре ввода-вывода sfr установится бит bit. Грех не воспользоваться готовеньким, тем более что библиотечные элементы, как правило, хорошо оптимизированы и протестированы.

Теперь по поводу:
DruidCat писал(а):
Код:
//Вызывать из основного модуля эту функцию не нужно.
__attribute__((naked, section(".init7")))
void init_usart (void)// Функция настройки параметров USART.
Программирование - это постоянный выбор компромисса между несколькими правильно работающими вариантами: быстродействие против компактности кода, эффективность против скорости разработки и т.д. Крайне редко попадаются идеальные варианты, гораздо чаще - более предпочтительные в данных конкретных условиях. В решении вынести инициализацию в секцию .init7 также есть свои плюсы и минусы.

Плюсы: неявный вызов функции инициализации гарантирует, что клиент не забудет инициализировать USART и не попытается слать в него данные без инициализации.

Минусы: если Вы сохраните взятый высокий темп обучения, то довольно скоро освоите C (он на самом деле весьма прост) и перейдете на новый уровень - разработку качественного программного обеспечения. Например, если вооружитесь технологией разработки ПО через тестирование (TDD), то вместо
DruidCat писал(а):
Проверял работу на симуляторе. Вроде работает. :)))
начнете говорить: "Я завершил тестирование программы, все тесты прошли успешно". Будете стремиться к максимальному покрытию кода тестами, в том числе и кода инициализации. Для полноценного тестирования нетривиального кода инициализации, скорее всего, потребуются мок-объекты. В случае неявной инициализации возможны проблемы с тестированием этой части кода. По крайней мере, я не очень представляю себе, как это сделать с моими предпочтительными инструментами модульного тестирования кода C Unity и CMock.

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

_________________
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: WinAvr в вопросах и ответах
СообщениеДобавлено: Пт сен 07, 2012 14:47:57 
Друг Кота

Карма: -18
Рейтинг сообщений: 29
Зарегистрирован: Вс дек 05, 2010 06:10:34
Сообщений: 4583
Откуда: ЮВ
Рейтинг сообщения: 0
Goldsmith писал(а):
Код:
      while ((UCSRA & _BV(UDRE)) == 0);   //Пауза, цикл работает пока регистр данных не опустошён

1. Вместо (условие == 0) с таким же успехом можно писать (!условие). Второй вариант читабельнее, поскольку конфузливо скрывает факт, что C так и не обзавелся полноценным булевским типом.

Ничего там "читабельнее" нет...
Так... персональная привычка... не более...
Восклицательный знак гораздо проще не заметить...
Цитата:
2. Вместе с макросом _BV в библиотеке определены также еще несколько полезных макросов для работы с битами. Один из них:
Код:
#define loop_until_bit_is_set( sfr, bit ) do { } while (bit_is_clear(sfr, bit))
ожидает в пустом цикле, пока в регистре ввода-вывода sfr установится бит bit. Грех не воспользоваться готовеньким, тем более что библиотечные элементы, как правило, хорошо оптимизированы и протестированы.

Грех "воспользоваться готовеньким"... ))))))))))))))
При малейшем сбое или ошибке можно долго ломать голову... почему зависло или пересбрасывается... )))))))))
Да ещё и надеяться на то... "что библиотечные элементы, как правило, хорошо оптимизированы и протестированы"... )))))
Да и сам макрос _BV галимый ацтой... нигде в природе больше не встречается... )))))))

_________________
"Я не даю готовых решений, я заставляю думать!"(С)


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 2195 ]     ... , , , 61, , , ...  

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 22


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y