DruidCat писал(а): А как очищать буфер? Нулей в его записать?
Ну зачем же записать нулей? можно просто queueC обнулить после передачи последнего символа.
DruidCat писал(а): А как очищать буфер? Нулей в его записать?
DruidCat писал(а):Я человек новый в AVR, но хочу задать тебе вопрос, а ты Fuses (Фьюзы) прошил в своем МК на внешний кварц 8 Мгц?
maff писал(а):Шью скомпиленое в CVAVR получаю 8Mhz. А если скомпиленое WinAVR'ом то 1MHz.
zero648 писал(а):Это в симуляторе так частота настраивается, т.е. подразумевается, что камень будет прошит (не компилятором) под заявленную частоту, а в железе частота только по фузам.
zero648 писал(а):maff , скорей всего у компиляторов разная оптимизация кода, да и в цикле не понятно где прерывание таймера включится. Попробуй использовать режим сна, так хотябы можно прерывания таймера котролировать, да и процик отоспица, когда он спит, жрать не просит
Код: Выделить всё
CLKPR=0x80; //Установка бита CLKPCE/ Разрешает изменение предделителя
CLKPR=0x00;The CLKPCE bit must be written to logic one to enable change of the CLKPS bits. The CLKPCE
bit is only updated when the other bits in CLKPR are simultaneously written to zero. CLKPCE is
cleared by hardware four cycles after it is written or when CLKPS bits are written. Rewriting the
CLKPCE bit within this time-out period does neither extend the time-out period, nor clear the
CLKPCE bit.
vitalik_1984 писал(а):DruidCat писал(а): А как очищать буфер? Нулей в его записать?
Ну зачем же записать нулей? можно просто queueC обнулить после передачи последнего символа.
Код: Выделить всё
ISR(USART_TXC_vect){ //Подпрограмма обработки прерывания при завершении передачи очередного символа
if (queueC != sendC){ UDR = queue[sendC++];} //Если был передан не последний символ, то передаем текущий и увеличиваем счетчик переданных на 1
if (sendC>50) {sendC=0;}
}
Ненадежное решение. Закладываетесь на то, что передача заведомо должна уложиться в определенное время.DruidCat писал(а):while (1){ //Бесконечный цикл
SEND_USART(CHAR_NUMBERS); //Отсылаем массив CHAR_NUMBERS в функцию SEND_USART
_delay_ms(1000); //Пауза в 1сек
SEND_USART(HIGHT); //Отсылаем массив HIGHT в функцию SEND_USART
_delay_ms(1000); //Пауза в 1сек
}
vitalik_1984 писал(а):например так:Код: Выделить всё
ISR(USART_TXC_vect){ //Подпрограмма обработки прерывания при завершении передачи очередного символа
if (queueC != sendC){ UDR = queue[sendC++];} //Если был передан не последний символ, то передаем текущий и увеличиваем счетчик переданных на 1
if (sendC>50) {sendC=0;}
}
но это опять же нужно целиком все согласовывать, у вас ведь очередь всего 50 символов, а это нигде не контролируется

Goldsmith писал(а):Ненадежное решение. Закладываетесь на то, что передача заведомо должна уложиться в определенное время.DruidCat писал(а):while (1){ //Бесконечный цикл
SEND_USART(CHAR_NUMBERS); //Отсылаем массив CHAR_NUMBERS в функцию SEND_USART
_delay_ms(1000); //Пауза в 1сек
SEND_USART(HIGHT); //Отсылаем массив HIGHT в функцию SEND_USART
_delay_ms(1000); //Пауза в 1сек
}
В программе присутствует "магическое число" 1000 мс (1 с). По счастливой случайности этой задержки достаточно для отправки и данного преобразованного числа, и данного текстового сообщения при данной скорости 9600 бит/с. Достаточно либо повысить скорость передачи, либо увеличить длину сообщения, чтобы программа перестала работать. Такой код нельзя считать качественным.
Может я и плохо ищу, меня постоянно отвлекает моя беременная жена:(

Код: Выделить всё
//********************************************************************************
//
// Автор : DruidCat
//
// МК : ATMega8L
//
// Компилятор : WinAVR
//
// Назначение : Выводим число и строку по USART через универсальную функцию
//
// Дата : 03.09.2012
//
//********************************************************************************
#include <avr/io.h>
#include <stdlib.h> //Вызов функции itoa, ltoa
#define F_CPU 8000000UL //Частота МК
#define USART_SPEED 9600 //Скорость USART желаемая
#define BAUD ((F_CPU/(USART_SPEED*16UL)) + 1) //Формула расчета БОД
unsigned char queueC, sendC; //Индексы текущего и переданного символа
unsigned char queue[50]; //Очередь
void
SEND_USART (char *s)
{
//Функция формирования очереди символов из строки
queueC = 0; //Текущий символ - первый
sendC = 0; //Первый символ для передачи
queue[queueC++] = 0x0D; //Добавляем в конец очереди символы
queue[queueC++] = 0x0A; //возврата каретки и переноса строки
while (*s)
{
if (queueC>50)//Если колличество символов массива больше 50, то...
{
queueC = 50;//счетчик символов в массиве равен максимальному значению 50
}
queue[queueC++] = *s++; //Просматриваем строку и помещаем в очередь символы
}
while (queueC != sendC) //Запускаем цикл передачи символов пока не будет равенство queue и sendC
{
UDR = queue[sendC++]; //Передаем текущий символ и увеличиваем счетчик переданных на 1
while ((UCSRA & (1 << UDRE)) == 0); //Пауза, цикл работает пока регистр данных не опустошён
}
}
void
INIT_USART (void)
{
//Функция настройка USART
UCSRB = (0 << RXCIE) | (1 << TXCIE) | (0 << RXEN) | (1 << TXEN); //Активизируем прерывание по окончание передачи и передатчик
UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0); //размер слова 8 разрядов
UBRRH = (unsigned char) (BAUD >> 8); //Скорость передач
UBRRL = (unsigned char) BAUD; //Скорость передач
}
int
main (void)
{
INIT_USART (); //Вызываем функцию для настройки USART
char HIGHT[] = "Высота 239"; //Массив символов HIGHT
long int NUMBERS = 1234567; //Число для преобразования NUMBERS
char *CHAR_NUMBERS; //Результат преобразования будет сюда записываться CHAR_NUMBERS
char BUFFER[20]; //Символьный буфер преобразуемого числа
CHAR_NUMBERS = ltoa (NUMBERS, BUFFER, 10); //Отсылаем в функцию ltoa число
while (1) //Бесконечный цикл
{
SEND_USART (CHAR_NUMBERS); //Отсылаем массив CHAR_NUMBERS в функцию SEND_USART
SEND_USART (HIGHT); //Отсылаем массив HIGHT в функцию SEND_USART
}
}Код: Выделить всё
queue[queueC++] = 0x0D; //Добавляем в конец очереди символы
queue[queueC++] = 0x0A; //возврата каретки и переноса строки
Код: Выделить всё
UCSRB = (0 << RXCIE) | (1 << TXCIE) | (0 << RXEN) | (1 << TXEN); //Активизируем прерывание по окончание
Код: Выделить всё
UDR = queue[sendC++]; //Передаем текущий символ и увеличиваем счетчик переданных на 1
while ((UCSRA & (1 << UDRE)) == 0); //Пауза, цикл работает пока регистр данных не опустошён
Код: Выделить всё
unsigned char queue[50]; //Очередь
Так в C# указателями практически и не пользуются, слава богу. Оставлена на всякий случай лазейка для совместимости с "нативным" кодом, но используется крайне редко за ненадобностью в большинстве задач.DruidCat писал(а):Я все замечания исправил, кроме пункта №4 по указателям. Мне они даются крайне тяжело, не знаю почему. Еще с универа, когда я немного изучал С#.
Скачайте книгу Ted Jensen, Tutorial on Pointers and Arrays in C. Небольшая, но толковая, к тому же официально бесплатная. Развеет любой ступор, будете чувствовать себя среди указателей и массивов, как рыба в воде.DruidCat писал(а):У меня ступор в голове происходит, когда я начинаю пользоваться указателями.
Код: Выделить всё
...
unsigned char queue[50]; //Очередь
...
while (*s)
{
if (queueC>50)//Если колличество символов массива больше 50, то...
{
queueC = 50;//счетчик символов в массиве равен максимальному значению 50
}
queue[queueC++] = *s++; //Просматриваем строку и помещаем в очередь символы
}
...