12.03.2010, 11:08
|
|
Временная регистрация
Регистрация: 04.08.2006
Сообщений: 67
Сказал спасибо: 2
Сказали Спасибо 20 раз(а) в 11 сообщении(ях)
|
Re: На WinAVR + AVR Studio c CVAVR
Продолжаем разговор.
Для начала немного теории:
Что такое FIFO – стек, первым вошел, первым вышел. Для его реализации нужен массив, указатель начала, указатель конца, и счетчик количества данных. Для наглядности лучше использовать структуру.
Потоки и файлы:
Файл – некое устройство ввода вывод способное принимать и/или отдавать данные.
Поток – последовательность данных может “втекать” в файл и/или “вытекать” из файла.
Программа:
Код:
|
/* Файл main.c */
//#define F_CPU 16000000UL
#include ‹avr/io.h›
#include ‹stdio.h› // стандартная библиотека ввода/вывод
#include ‹avr/pgmspace.h› // утилиты пространства программ
#include "uart.h"
// Создаем поток для ввода/вывода на/с UART для использования стандартных
// функции ввод/вывода
FILE uart_file = FDEV_SETUP_STREAM(uart_put, uart_get, _FDEV_SETUP_RW);
int main (void)
{
uart_init(); // название Ф-ции говорит само за себя
stdout = stdin = &uart_file; // теперь стандартные потоки ссылаются на наш поток
char str[50];
printf_P(PSTR("Hello, World!\n\r"));
printf_P(PSTR("Input string:"));
scanf_P(PSTR("%49s"),&str);
printf_P(PSTR("%s\n\r"),str);
fprintf(&uart_file, "Bye-bye\n\r"); // Так можно выбирать с каким именно
// потоком работать (для примера)
while (1);
return 0;
} |
Заголовочный файл для UART
Код:
|
/* file "uart.h" */
#ifndef UART
#define UART
#include ‹stdio.h›
#include ‹avr/io.h›
#include ‹avr/interrupt.h›
#define UART_FIFO_SIZE 64 // Размер FIFO
#define UART_BAUD 9600 // Скороть UART
void uart_init(void);
int uart_get (FILE *stream);
uint8_t uart_test (void);
int uart_put (char d, FILE *stream);
#endif /* end UART */ |
Можно наверно назвать драйвером UART:
Код:
|
/* file "uart.c" */
#include "uart.h"
typedef struct { // Структура для FIFO
uint8_t idx_w; // Указатель на конец очереди FIFO
uint8_t idx_r; // Указатель на начало очереди FIFO
uint8_t count; // Счетчик количества данных в FIFO
uint8_t buff[UART_FIFO_SIZE]; // Сам FIFO
} FIFO;
static volatile
FIFO txfifo, rxfifo;
/* Initialize UART */
void uart_init()
{
rxfifo.idx_r = 0;
rxfifo.idx_w = 0;
rxfifo.count = 0;
txfifo.idx_r = 0;
txfifo.idx_w = 0;
txfifo.count = 0;
UBRRL = (F_CPU / (16UL * UART_BAUD)) - 1; // Настраиваем скорость работы UART
UCSRB = _BV(RXEN)|_BV(RXCIE)|_BV(TXEN); // Включаем: прием, вызов прерывания по приему, передачу
}
uint8_t uart_test (void)
{
return rxfifo.count;
}
int uart_get (FILE *stream) // Ф-ция чтения FIFO для приемника
{
char d;
uint8_t i;
i = rxfifo.idx_r;
while(rxfifo.count == 0); // Ожидание входящих данных
d = rxfifo.buff[i++];
cli();
rxfifo.count--;
sei();
if(i ›= UART_FIFO_SIZE)
i = 0;
rxfifo.idx_r = i;
uart_put(d,stream); // Эхо ответ
return d;
}
int uart_put (char d, FILE *stream) // Ф-ция записи в FIFO для передатчика
{
uint8_t i;
i = txfifo.idx_w;
while(txfifo.count ›= UART_FIFO_SIZE); // ждем когда освободится место в FIFO
txfifo.buff[i++] = d;
cli();
txfifo.count++;
UCSRB |= _BV(UDRIE); // Включаем вызов прерывания по освобождению буфера передатчика
sei();
if(i ›= UART_FIFO_SIZE)
i = 0;
txfifo.idx_w = i;
return 0;
}
ISR(USART_RXC_vect) // Прерывание по приему
{
uint8_t d, n, i;
d = UDR;
n = rxfifo.count;
if(n ‹ UART_FIFO_SIZE) // Если FIFO заполнен данные начнут теряться
{
rxfifo.count = ++n;
i = rxfifo.idx_w;
rxfifo.buff[i++] = d;
if(i ›= UART_FIFO_SIZE)
i = 0;
rxfifo.idx_w = i;
}
}
ISR(USART_UDRE_vect) // Прерывание по освобождению буфера передатчика
{
uint8_t n, i;
n = txfifo.count;
if(n) {
txfifo.count = --n;
i = txfifo.idx_r;
UDR = txfifo.buff[i++];
if(i ›= UART_FIFO_SIZE)
i = 0;
txfifo.idx_r = i;
}
if(n == 0) // если FIFO пуст,
UCSRB &= ~_BV(UDRIE); // то выключаем вызов прерывания по освобождению буфера передатчика
} |
|
|
|
Эти 4 пользователя(ей) сказали Спасибо Vetal-soft за это сообщение:
|
|
|
14.03.2010, 21:35
|
|
Прохожий
Регистрация: 08.09.2009
Сообщений: 6
Сказал спасибо: 2
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: на WinAVR + AVR Studio c CVAVR
Сообщение от Vetal-soft
|
Работает одинаково т.к.
Код:
|
#define _BV(bit) (1 ‹‹ (bit)) |
и при оптимизации код в ассемблере будет таким
|
на ассемблере этот код скорее всего будет выглядеть так
Код:
|
in temp,PORTA
andi temp 0b00010000
out PORTA ,temp |
|
|
|
|
15.03.2010, 11:49
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
|
Re: На WinAVR + AVR Studio c CVAVR
Сообщение от spballiance
|
несколько страниц обсуждается какая-то мелочь _BV. а на мой последний вопрос не ответили
|
Э.. а где вопрос?
Сообщение от Zemlyanov
|
А если определенный бит нужно выставить в 0, что писать в место _BV. Или для 0 только так (0‹‹4) ?
|
Вот так можно:
Код:
|
TCCR1A = _BV(CS12) |/* _BV(CS11) |*/ _BV(CS10); |
Но такие комментарии не могут быть вложенными, т.е. участок кода, содержащий такую конструкцию уже нельзя закомментить с помощью /*
|
|
|
|
15.03.2010, 13:42
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
|
Re: На WinAVR + AVR Studio c CVAVR
Сообщение от andries5
|
В ходе работы программы нельзя.
|
TCCR1A |= (1‹‹CS12)|(0‹‹CS11)|(1‹‹CS10);
И уже можно
Я еще в 21 сообщении написал, что так делаю я и почему так делаю.И про то, что не навязываю этот метод. Каждый должен выбрать сам как ему удобней.
А основные отличия GCC от CV все же это способы работы с еепром и константами во флеш. В GCC недостаточно объявить переменную в еепром, что бы затем использовать ее как обычную переменную. Для доступа к таким переменным используются макросы из eeprom.h - eeprom_read_byte и т.д. Причем параметром для них должен быть указатель на переменную в еепром, а не сама переменная.
Код:
|
#include ‹inttypes.h›
#include ‹avr/eeprom.h›
uint8_t EEMEM EepromVar;
// можно сразу инициализировать переменную, тогда компилятор создаст файл для еепром - его можно записать в кристалл программатором.
uint8_t volatile TestVar;
TestVar = eeprom_read_byte(&EepromVar); // прочитать переменную
eeprom_write_byte(&EepromVar,TestVar); // запись в переменную в еепром |
Если в еепром размещена структура, то можно использовать макрос eeprom_read_block ( eeprom_write_block для записи)
Код:
|
#include ‹inttypes.h›
#include ‹avr/eeprom.h›
typedef struct
{
uint8_t a;
uint8_t b;
uint8_t c;
} tpMyStruct;
tpMyStruct EEMEM EepStruct; // объявление структуры в еепром
tpMyStruct MyStruct; // это обычная структура в ОЗУ
eeprom_read_block(&MyStruct, &EepStruct, sizeof(EepStruct)); // считать структуру из еепром в ОЗУ
eeprom_write_block(&MyStruct, &EepStruct, sizeof(EepStruct)); // сохранить структуру в еепром |
Стоит еще учесть, что макросы инлайнятся в код, это не функции. Поэтому размер программы может возрастать. Можно сделать одну функцию с макросом внутри и вызывать ее по мере необходимости. Будет чуть чуть медленнее, но программа станет меньше.
А при записи замедление не заметно.
С константами в памяти программ почти аналогично, за исключением записи. Смотрите макрос pgmspace.h
Последний раз редактировалось kison; 15.03.2010 в 14:07.
|
|
|
|
17.03.2010, 21:09
|
|
Почётный гражданин KAZUS.RU
Регистрация: 19.02.2008
Сообщений: 1,802
Сказал спасибо: 124
Сказали Спасибо 602 раз(а) в 419 сообщении(ях)
|
Re: На WinAVR + AVR Studio c CVAVR
Начало было хорошее, и вдруг затихло. А жаль.
|
|
|
|
18.03.2010, 08:28
|
|
Частый гость
Регистрация: 14.11.2009
Сообщений: 47
Сказал спасибо: 6
Сказали Спасибо 1 раз в 1 сообщении
|
Re: На WinAVR + AVR Studio c CVAVR
Сообщение от Vetal-soft
|
/* file "uart.c" */
|
Сообщение от Vetal-soft
|
/* Файл main.c */
|
А как компилить два исходника в один hex?
|
|
|
|
18.03.2010, 09:38
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.05.2006
Адрес: Москва
Сообщений: 3,559
Сказал спасибо: 76
Сказали Спасибо 326 раз(а) в 230 сообщении(ях)
|
Re: На WinAVR + AVR Studio c CVAVR
Другие файлы нужно включить директивами прерпроцессора #include в тот файл в котором есть главная функция Си под названием main()
Пример в САМОМ начале этой странички !!!
__________________
Обучалка AVR PIC ARM начинающим программирование курс самоучитель шаг за шагом с нуля, CVAVR, PROTEUS, MPLAB, WinAVR, IAR, KEIL электроника - http://proavr.narod.ru
|
|
|
|
18.03.2010, 10:09
|
|
Почётный гражданин KAZUS.RU
Регистрация: 19.02.2008
Сообщений: 1,802
Сказал спасибо: 124
Сказали Спасибо 602 раз(а) в 419 сообщении(ях)
|
Re: На WinAVR + AVR Studio c CVAVR
Если компилировать в WinAVR, в утилите MFile указывается тип процессора, частота, степень оптимизации и т.д. в том числе и дополнительные довключаемые файлы.
|
|
|
|
18.03.2010, 14:48
|
|
Прописка
Регистрация: 21.09.2009
Сообщений: 218
Сказал спасибо: 1
Сказали Спасибо 29 раз(а) в 27 сообщении(ях)
|
Полуофф
0xFF››2. Где-то читал, что шизофреники к месту и не к месту меняют размер шрифта, используют курсив, раскрашивают техт разноцветными шрифтами.
Стоит задуматься тем, кто продвигает/посещает небезызвестный курс.
Лично меня разноцветный текст сильно раздражает.
|
|
|
|
18.03.2010, 14:55
|
|
Почётный гражданин KAZUS.RU
Регистрация: 19.08.2006
Адрес: Львов
Сообщений: 1,616
Сказал спасибо: 65
Сказали Спасибо 315 раз(а) в 264 сообщении(ях)
|
Re: на WinAVR + AVR Studio c CVAVR
Сообщение от john1170
|
на ассемблере этот код скорее всего будет выглядеть так
Код:
|
in temp,PORTA
andi temp 0b00010000
out PORTA ,temp |
|
Я пишу в ИАРе. И пользуюсь такими макросами:
Код:
|
#define SETBIT(x,y) (x|=(1‹‹y))
#define CLRBIT(x,y) (x&=~(1‹‹y))
#define INVBIT(x,y) (x^=(1‹‹y))
#define CHKBIT(x,y) (x&(1‹‹y))
#define BITON(x,y) (x&(1‹‹y))
#define BITOFF(x,y) (!(x&(1‹‹y))) |
Макросы CHKBIT и BITON - синонимы. Не забвать указывать PIN а не PORT
Пример использования:
Код:
|
#define BUZZ_PIN 0x07
#define BEEP_ON CLRBIT(PORTC,BUZZ_PIN)
#define BEEP_OFF SETBIT(PORTC,BUZZ_PIN) |
Транслируется именно в коды управления битами, а не чтение-модификация-запись.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 13:22.
|
|