Ребята, помогите. Я по поводу функции itoa. Вот листинг: //******************************************************************************** // // Автор : DruidCat // // МК : ATMega8L // // Компилятор : WinAVR // // Назначение : Выводим по USART строку "ВЫСОТА 239" // // Дата : 04.08.2012 // //******************************************************************************** #include <avr/io.h> #include <util/delay.h> //Для вызова функции _delay_ms() #define F_CPU 8000000UL //Частота МК #define USART_SPEED 9600 //Скорость USART желаемая #define BAUD ((F_CPU/(USART_SPEED*16UL)) + 1) //Формула расчета БОД #include <stdlib.h> //Для вызова ыункции itoa #include <string.h> //Для вызова функции strlen
void SEND_USART(char WORD[]){ //Функция вывода массива for(int i=0;i<11;i++){ //Цикл, пока i не достигнет 11, он будет работать UDR = WORD[i]; //Выводим посимвольно символы в масиве _delay_ms(1); //Пауза 1мс } }
void REVERSE(char s[]) { //reverse: переворачиваем строку s на месте int i, j; char c; for (i = 0, j = strlen(s)-1; i<j; i++, j--) { c = s[i]; s[i] = s[j]; s[j] = c; } }
void itoa(int n, char s[]) //itoa: конвертируем n в символы в s { int i, sign;
if ((sign = n) < 0) //записываем знак n = -n; //делаем n положительным числом i = 0; do { //Цикл, генерирующий цифры в обратном порядке s[i++] = n % 10 + '0'; //берем следующую цифру, к десятичному остатку прибовляем 0х48 и получаем символ цифры в ASCII } while ((n /= 10) > 0); //удаляем цифру деля на 10 'n=n/10' если n>0 if (sign < 0) //Если <0 то... s[i++] = '-'; //Добавляем знак '-' если он есть s[i] = '\0'; //Конец строки REVERSE(s); //Реверсируем массив цифр } int main (void) { UCSRB = (0<<RXCIE)|(0<<TXCIE)|(0<<RXEN)|(1<<TXEN); //Активизируем передатчик UCSRC=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); //размер слова 8 разрядов UBRRH = (unsigned char)(BAUD >> 8 ); //Скорость передач* UBRRL = (unsigned char)BAUD; //Скорость передач* char HIGHT[]="Высота 239 "; //Словесный масив
while (1) //Бесконечный цикл { //Отсылаем текст через небольшую паузу SEND_USART(HIGHT); //Отсылаем массив HIGHT через функцию SEND_USART _delay_ms(1000); //Пауза в 1сек REVERSE(HIGHT); //Вызываем функию reverse для реверса массива HIGHT } }
При написании программы, я её поэтапно проверял. Написал функцию по выводу массива по USART, работает. Провери функцию reverse, которая реверсирует масивв, работает. А как только я написал функцию itoa,WINAVR выда ошибку error: conflicting types for 'itoa' (путь нахождения stdlib.h у меня в винде)stdlib.h:406: error: previous declaration of 'itoa' was here
Помогите как правильно листинг написать, я в С вообще профан, я искренне верю, что тупо мне знаний не хватает. Я функцию itoa размещал в главной функции main, компилятор ошибок никаких не выдал. Но я не могу ей воспользоваться, не знаю как её правильно вызвать. хехехе
_________________ Кот должен прожить жизнь без сожаления.
Во Во, мне нужно, чтоб эта функция возвращала char, вы не подскажете, как мне это сделать и чтоб она не конфликтовала с уже объявленой функцией в stdlib.h. Я, если честно, вообще не умею пользоваться подключаемыми бибиотеками. У меня познания в С детские. Из учебного пособия, которым я пользуюсь, есть у меня Программирование на языке С для AVR и PIC в редакции Шпака где для программировария используется WINAVR. Но как я прочитал на вашем форуме, эту книгу очень сильно обижают, и понятно почему, т.к. там миллиард ошибок, и почти все переписанные мной листинги не работали. Их приходилось изменять. Подскажите нормальную книгу на РУССКОМ по программированию AVR на С, все у меня имеющиеся книги на ассемблере, а в дебри ассемблера мне нет желания и времени вникать. Сам я по образованию инженер - электрик, и работаю в сфере больших напряжений. А AVR занимаюсь для души. Если вам не сложно, дайте мне пожалуйста пример написания листинга правильной функции itoa, я буду вам по кошачи багодарен.
_________________ Кот должен прожить жизнь без сожаления.
Подскажите нормальную книгу на РУССКОМ по программированию AVR на С
Боюсь, что нормальной книги на русском мы вряд ли дождемся. Из того, что есть, имеет смысл посмотреть: Белов А.В. Самоучитель разработчика устройств на микроконтроллерах AVR. Далека от идеала, конечно, но остальное, что доводилось листать, - вообще полный хлам.
Лучше почитайте отдельно хороший учебник C (без привязки к МК) + фирменную документацию от Atmel, там полно небольших фрагментов кода на C с учетом специфики МК. Почерпнете гораздо больше.
_________________ Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет. J. Ganssle
Белов А.В. Самоучитель разработчика устройств на микроконтроллерах AVR то что надо, спасибо за книгу Goldsmith. Щас перекинул на свою е-книгу и буду на работе потихоньку изучать учебник. А по функции itoa не подскажете, где у меня ошибка?
_________________ Кот должен прожить жизнь без сожаления.
А по функции itoa не подскажете, где у меня ошибка?
DruidCat писал(а):
stdlib.h:406: error: previous declaration of 'itoa' was here
Компилятор жалуется, что ему ранее уже попадалось определение itoa в файле stdlib.h
Если хотите поэкспериментировать со своим вариантом, то переименуйте его, скажем, в my_itoa, в стандартной библиотеке такой функции точно нет. Если хотите воспользоваться библиотечным вариантом, то попросту удалите свой конфликтующий.
_________________ Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет. J. Ganssle
Блин, я догнал. Получается, что ту функцию (itoa), которую я написал, можно назвать как угодно, и не обязательно подключать бибиотеку stdlib.h. Получается, как бы я сам написал функцию. А если я захочу воспользоваться стандартной функцией itoa из бибиотеки stdlib.h, свою я удаляю. И пишу:
#include <stdlib.h> int main(void) { char a; int b = 12345; a[] = itoa (b); }
Так? или я что то не так написал?
_________________ Кот должен прожить жизнь без сожаления.
Char это символ, а a[] это массив символов. Как мне правильно записать, чтоб воспользоваться itoa? char a[]; Разве так можно? Будет ошибка.
Ребята, не получается. Я пробовал использовать функцию написанную в листинге. void itoa(int n, char a[]) Как я понял, char a[] - это буфер, но когда я вызываю эту функцию:
int a; itoa(a);
выдается ошибка too few arguments to function 'itoa' Несколько аргументов в функции itoa
Блин, не понимаю. Мужики, вы же серьезные ребята, в Си профессионалы, подскажите проклятому нубу, как запустить мне функцию itoa из библиотеки stdlib.h
_________________ Кот должен прожить жизнь без сожаления.
Спасибо vitalik_1984 за книжку, я её сейчас скачал. Я пишу в этой ветке форума, так как пишу программки именно в WINAVR. А можно мне задать маленький вопрос? Как мне пользоваться этим замечательным форумом? Получается что я нуб безобразный, задаю тупые вопросы и пишу не по теме постоянно. Наверно, мне нужно убить себя об стену. PS: Ребята, спасибо всем за помощь.
_________________ Кот должен прожить жизнь без сожаления.
Всем спасибо, кто мне помогал. Вот листинг программы, который я написал. В нем число превращается в массив символов с помощью функции itoa и передается на терминал по USART, данный пример более экономен по памяти, нежели функция printf в два раза. Выкладываю этот листинг для таких же новичков, как и я. Вдруг, кто нибуть будет искать ответ на подобный вопрос, пользуйтесь на здоровье. //******************************************************************************** // // Автор : DruidCat // // МК : ATMega8L // // Компилятор : WinAVR // // Назначение : Выводим число по USART // // Дата : 16.08.2012 // //******************************************************************************** #include <avr/io.h> #include <util/delay.h> //Для вызова функции _delay_ms() #define F_CPU 8000000UL //Частота МК #define USART_SPEED 9600 //Скорость USART желаемая #define BAUD ((F_CPU/(USART_SPEED*16UL)) + 1) //Формула расчета БОД #include <string.h> //Для вызова функции strlen
void SEND_USART(char WORD[]){ //Функция вывода массива for(int i=0;i<9;i++){ //Цикл, пока i не достигнет 9, он будет работать UDR = WORD[i]; //Выводим посимвольно символы в масиве _delay_ms(1); //Пауза 1мс } }
void REVERSE(char s[]) { //reverse: переворачиваем строку s на месте int i, j; char c; for (i = 0, j = strlen(s)-1; i<j; i++, j--) { c = s[i]; s[i] = s[j]; s[j] = c; } }
void itoa(long int n, char s[]) //itoa: конвертируем n в символы в s { long int i, sign;
if ((sign = n) < 0) //записываем знак n = -n; //делаем n положительным числом i = 0; do { //Цикл, генерирующий цифры в обратном порядке s[i++] = n % 10 + '0'; //берем следующую цифру, к десятичному остатку прибовляем 0х48 и получаем символ цифры в ASCII } while ((n /= 10) > 0); //удаляем цифру деля на 10 'n=n/10' если n>0 if (sign < 0) //Если <0 то... s[i++] = '-'; //Добавляем знак '-' если он есть s[i] = '\0'; //Конец строки REVERSE(s); //Реверсируем массив цифр
}
int main (void) { UCSRB = (0<<RXCIE)|(0<<TXCIE)|(0<<RXEN)|(1<<TXEN); //Активизируем передатчик UCSRC=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); //размер слова 8 разрядов UBRRH = (unsigned char)(BAUD >> 8 ); //Скорость передач* UBRRL = (unsigned char)BAUD; //Скорость передач*
long int NUMBERS = 123456789; char STRING[5]; itoa(NUMBERS, STRING); //Отсылаем в функцию itoa число и указываем буфер массива while (1) //Бесконечный цикл { //Отсылаем текст через небольшую паузу SEND_USART(STRING); //Отсылаем массив string в функцию SEND_USART _delay_ms(1000); //Пауза в 1сек } }
_________________ Кот должен прожить жизнь без сожаления.
Поздравляю с почином. Я так понимаю, уже успели попробовать программу в деле или хотя бы на модели в Proteus'е или VMLAB'е?
Если программа уже работает, можно ее еще подшлифовать. Позвольте несколько рекомендаций.
Прежде всего, Вы совершенно правильно предусмотрели возможность переопределять макросами при необходимости такие константы, как частоту процессора и скорость передачи UART вместо того, чтобы искать по всему тексту "магические числа". Но в то же время остался один существенный изъян: интервал между посылками задается временной паузой:
Этой задержки в обрез достаточно для выбранной Вами скорости 9600 бит/с; однако, если, к примеру, захотите удвоить скорость до 19200, данной паузы будет уже недостаточно, и посылки будут искажены. UART имеет бит готовности передатчика, Вы легко найдете его в описании МК. Этот бит устанавливается, когда буфер передатчика пуст и можно загружать в него следующий байт. Вместо фиксированной паузы опрашивайте этот бит - и получите надежную, универсальную для любых скоростей передачи программу. (Еще лучше, конечно, работать по прерываниям, но с этим спешить сразу не следует).
Еще рекомендую вынести последовательность инициализации UART в отдельную подпрограмму, как Вы сделали с SEND_USART. Хотя эта последовательность и вызывается лишь один раз, но эту подпрограмму можно будет впоследствии использовать и в других программах, работающих с UART. (Кстати, имеет смысл также выделить подпрограмму вывода одного байта в UART, а строку выводить уже через нее).
Но все равно для первого раза, на мой взгляд, замечательно. Еще раз поздравляю.
_________________ Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет. J. Ganssle
Последний раз редактировалось Goldsmith Пт авг 17, 2012 00:53:26, всего редактировалось 1 раз.
Может и замечательНо, но есть одно но. Больше похоже, что код сделан копированием нужных кусков текста. Хочу сделать критическое замечание:
Код:
void SEND_USART(char WORD[]){ //Функция вывода массива for(int i=0;i<9;i++){ //Цикл, пока i не достигнет 9, он будет работать UDR = WORD[i]; //Выводим посимвольно символы в масиве _delay_ms(1); //Пауза 1мс } }
Судя по этому фрагменту все строки равной длины и равны 9. То есть если короче, то все равно будет выводить то, что после последнего символа, а то и вообще закончится крахом. Или если длиннее массив, то часть символов так и останется на месте.
На будущее лучше сразу стараться делать полезные функции, а не для конкретного случая.
Есть в интернете примеры с проверкой символа на ноль.Если ноль, то конец массива. Высылаем следующий символ, если он не равен нулю.
Как домашнее задание предлагаю придумать или списать данную функцию.
_________________ В поисках истины человек развивается.
Все верно, я из разных кусочков собрал этот листинг. Про функцию вывода символов по USART тоже вы говорите верно. Если массив символов будет например из двух символов, то большая беда случится. Я сейчас буду думать, как сделать функцию автоматической. Например в функции itoa добавить счетчик, который при делении на 10 прибавлял значение на +1. Нужно подумать.
_________________ Кот должен прожить жизнь без сожаления.
Этот бит устанавливается, когда буфер передатчика пуст и можно загружать в него следующий байт. Вместо фиксированной паузы опрашивайте этот бит - и получите надежную, универсальную для любых скоростей передачи программу. (Еще лучше, конечно, работать по прерываниям, но с этим спешить сразу не следует).
Блин, вот это идея. Кстати, по поводу прерываний и WINAVR. Я наконец то разобрался по прерыванию таймера, но у меня возникли некоторые трудности. Когда я переписывал листинг из учебника Шпака, там была инициализация функции прерывания по таймеру старой версии WINAVR. INTERRUPT (SIG_OVERFLOW1) Сейчас эти функции пишутся по другому. ISR(TIMER1_OVF_vect)
По предыдущему примеру таймеров, могу написать для USART прерывание. Я думаю так меня заработает прерывание по окончанию передачи USART для ATMega8.
#include <avr/interrupt.h>//Для доступа к функции sei() ISR(USART_TXC_vect){ ........ }
int main(void){ UCSRB = (0<<RXCIE)|(1<<TXCIE)|(1<<RXEN)|(1<<TXEN);//Активизируем прерывание по завершении передачи, приемник и передатчик sei(); while(1){} }
PS: Goldsmith я предыдущий листинг проверил и PROTEUS и на своем контроллере. Спасибо тебе что помог мне разобраться с функцией itoa
_________________ Кот должен прожить жизнь без сожаления.
Последний раз редактировалось DruidCat Пт авг 17, 2012 09:09:12, всего редактировалось 1 раз.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 422
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения