|
|
|
Статистика сайта |
Всего статей:
Категорий/рубрик:
Комментариев:
Пользователей: |
33
7
239
2123 |
|
Юмор от "Городок" |
|
|
Для корректного отображения этого элемента вам необходимо установить FlashPlayer и включить в браузере Java Script.
|
|
|
|
Модуль АЦП-8бит на МК ATmega8535. Часть 2 – Прошивка микроконтроллера |
Автор: Рудаков Г. В.
Дата: 2009-11-09 |
Продолжаем проект по созданию измерительного устройства АЦП модуля на микроконтроллере AVR. После того как была спроектирована принципиальная электрическая схема и печатная плата, требуется написать прошивку (микропрограмму) для микроконтроллера. Этим и займемся в данной статье.
Итак, в качестве редактора и компилятора я выбрал студию CodeVisionAVR за её многофункциональность, большое количество встроенных библиотек и присутствие генератора кода.
Создаем новый проект, и на предложение воспользоваться генератором кода, отвечаем согласием. Появилось окно с многочисленными вкладками (рисунок 1).

Рисунок 1 – Окно CodeWizardAVR. Выбор МК.
Первым делом укажем желаемый чип. В нашем случае это ATmega8535 (выбор данного микроконтроллера был обоснован в первой части статьи).
Затем переходим на вкладку «Timers». Здесь нас интересует инициализация таймера под номером 0. Выставляем значение частоты, то есть параметр «Clock Value» = 125 кГц (рисунок 2). Данное число берется не с потолка, а по рекомендациям из документации на МК. Производитель утверждает, что наибольшая точность преобразования достигается, если тактовая частота модуля АЦП находится в диапазоне 50…200 кГц.

Рисунок 2 – Окно CodeWizardAVR. Инициализация таймера.
Еще нам понадобится прерывание по переполнению таймера, поэтому ставим галочку «Overflow Interrupt». Параметр «Timer Value» пока не заполняем, его будем реинициализировать позже.
Переходим во вкладку «ADC – Analog to Digit Converter» (рисунок 3). Ставим галочки напротив «ADC Enabled» и «Interrupt». Выбираем частоту АЦП модуля равную частоте таймера (125 кГц), инициализацию которого выполнили раньше.

Рисунок 3 – Окно CodeWizardAVR. Инициализация АЦП.
И, выставляем значение параметра «Volt. Ref» - внутренний источник опорного напряжения с внешним конденсатором на ножке AREF. На данном этапе по инициализации АЦП модуля микроконтроллера это все. Позже вручную допишем еще несколько параметров (состояний регистров).
Теперь настроим LCD-дисплей. Его инициализации представлена на рисунке 4.

Рисунок 4 – Окно CodeWizardAVR. Инициализация LCD-дисплея.
На рисунке 4 видим, что программа автоматически в соответствие с кодом ее библиотеки, выдала нам требуемую «распиновку» для порта «С». Не забываем указать число символов в применяемом LCD-дисплее – это 8 символов в строке.
Следующим шагом настроим шину 1-Wire, используемую для подключения датчика температуры окружающей среды DS1820 (рисунок 5). Здесь требуется лишь указать используемый порт и номер ножки этого порта.

Рисунок 5 – Окно CodeWizardAVR. Инициализация шины 1-Wire.
И, в завершение инициализации, необходимо произвести настройку универсального синхро-асинхронного передатчика, коротко называемого USART (в нашем случае это всего лишь UART, так как синхронизация не используется, полагаемся на точность работы кварцевого резонатора). Он необходим для передачи произведенных аналогово-цифровых преобразований на ПК. Смотрим рисунок 6.

Рисунок 6 – Окно CodeWizardAVR. Инициализация USART.
Активируем галочки «Receiver» и «Transmitter» для возможности пользоваться и приемником и передатчиком. Чтобы посланные модулю команды с ПК не потерялись, активируем «Rx Interrupt» (прерывание по приему) с размером буфера в 8 символов.
Вроде все. Остальные настройки подправим ручками. Теперь сохраняем настройки и генерируем код (рисунок 7).

Рисунок 7 – Окно CodeWizardAVR. Сохраняем настройки и генерируем программный код.
Перед тем как перейти к комментированию получившегося программного кода сгенерированного CodeWizardAVR и дальнейшему написание остальной части микропрограммы для разрабатываемого модуля, рассмотрим составленный алгоритм «прошивки», представленный на рисунке 8.

Рисунок 8 – Алгоритм микропрограммы («прошивки» МК).
Представленный алгоритм описывать не буду, так как он достаточно прост. Если вдруг у Вас появятся вопросы, Вы всегда сможете задать их в своих комментариях.
Продолжаем написание «прошивки». Ниже будут представлены фрагменты получившегося кода с комментариями.
Первым делом функцией #include подключаем библиотеку «mega8535.h», которая описывает архитектуру МК. И, перед тем как подключить библиотеку шины 1-wire, необходимо определить на каком порту, и на каком бите будет находиться датчик dallas. Затем подключаем библиотеку «stdio.h», необходимую для использования таких простых функций как putchar, getchar и т. д. Все это делаем в следующих строках, точнее сделал за нас генератор CodeVision:
#include <mega8535.h>
#asm
.equ __w1_port=0x18 ;PORTB
.equ __w1_bit=4
#endasm
#include <1wire.h>
#include <ds18b20.h>
#include <delay.h>
#include <stdio.h>
Аналогичным образом как определяли шину 1-wire, инициализируем LCD-дисплей на порт «С» микроконтроллера через ассемблеровскую вставку, после чего подключаем библиотеку «lcd.h»:
#asm
.equ __lcd_port=0x15 ;PORTC
#endasm
#include <lcd.h>
Далее идем программный код, который сгенерировал целиком CodeVisionAVR. Этот фрагмент кода относится к UART. Если кто хочет полностью разобраться в сгенерированном коде, у него есть такая возможность прочитать задание №5 на сайте: http://www.123avr.com. Лично я так и поступил.
#define RXB8 1
#define TXB8 0
#define UPE 2
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7
#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<OVR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)
#define RX_BUFFER_SIZE 32
char rx_buffer[RX_BUFFER_SIZE];
#if RX_BUFFER_SIZE<256
unsigned char rx_wr_index,rx_rd_index,rx_counter;
#else
unsigned int rx_wr_index,rx_rd_index,rx_counter;
#endif
Для результата полученной выборки аналогово-цифрового преобразования определяем переменную «adc_data», а переменная «temp» для значений температуры окружающей среды.
#bit rx_buffer_overflow;
unsigned char adc_data;
int temp;
unsigned char TCNT0_value = 0x6;
Чтобы на LCD-дисплей можно было выводить русские символы, потребовалось определить массив и воспользоваться им в созданной функции «lcd_putsf_rus()», аргументом которой может быть русско-символьная строка.
flash char Decode2Rus[255-192+1]= {
0x41,0xA0,0x42,0xA1,0xE0,0x45,0xA3,0xA4,
0xA5,0xA6,0x4B,0xA7,0x4D,0x48,0x4F,0xA8,
0x50,0x43,0x54,0xA9,0xAA,0x58,0xE1,0xAB,
0xAC,0xE2,0xAD,0xAE,0xAD,0xAF,0xB0,0xB1,
0x61,0xB2,0xB3,0xB4,0xE3,0x65,0xB6,0xB7,
0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0x6F,0xBE,
0x70,0x63,0xBF,0x79,0xE4,0x78,0xE5,0xC0,
0xC1,0xE6,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7};
void lcd_putsf_rus(flash unsigned char *string)
{
char c;
while (c=*string++)
{
if(c>=192) lcd_putchar(Decode2Rus[c-192]);
else lcd_putchar(c);
}
}
Для того чтобы получилась некое подобие интерфейса человек-электроника, создадим служебные функции, которые будут выводить на дисплей информацию о готовности модуля и его работе.
void transfer()
{
lcd_clear();
lcd_gotoxy(2,0);
lcd_putsf_rus("идет");
lcd_gotoxy(0,1);
lcd_putsf_rus("передача");
}
void expectation()
{
lcd_clear();
lcd_gotoxy(0,0);
lcd_putsf_rus("ожидание");
lcd_gotoxy(1,1);
lcd_putsf_rus("команд");
}
void expectation()
{
lcd_clear();
lcd_gotoxy(1,0);
lcd_putsf_rus("МОДУЛЬ");
lcd_gotoxy(0,1);
lcd_putsf_rus("АЦП-8бит");
delay_ms(1500);
lcd_clear();
lcd_gotoxy(0,0);
lcd_putsf("made by");
lcd_gotoxy(1,1);
lcd_putsf("GrigaN");
delay_ms(1500);
expectation();
}
Значение температуры окружающей среды получаем по требованию с ПК. Определим для этого отдельную самостоятельную функцию get_send_temp(), которая поcле получения с датчика dallas значения температуры будет отправлять его посредством UART.
void get_send_temp()
{
putchar(253);
temp = 10*(ds18b20_temperature(0));
putchar((char)(temp>>8));
putchar((char)(temp));
}
Далее я пропускаю кусок кода, отвечающий за обработку прерывания от приёмника UART.Читаем на странице сайта: http://www.123avr.com. задание №5.
Сердцем программы является ниже представленный листинг кода. Здесь в обработчике прерывания таймер сам себя реинициализирует из константы TCNT0_value и запускает одиночное аналого-цифровое преобразование.
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=TCNT0_value;
ADCSRA.6=1;
}
После того как был получен результат преобразования, генерируется прерывание, в обработчике которого фильтруем полученное измерение и отправляем его по UART функцией putchar().
interrupt [ADC_INT] void adc_isr(void)
{
if (ADCW<200)
{
adc_data=ADCW;
putchar(254);
putchar(adc_data);
}
}
Переходим к инициализации основных элементов МК. Особое внимание следует уделить инициализации UART и ADC. Если Вы помните из рисунка 6 CodeWizardAVR не позволил указать нужную скорость передачи в 500000 Bp. Правим регистр UBRR согласно таблице 13.10 в главе 13 источника [1].
UCSRA=0x00;
UCSRB=0x98;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x00;
В инициализацию АЦП требуется добавить назначение регистра ADMUX, значением которого устанавливаются используемые «ноги» микроконтроллера непосредственно к которым подключается термопара. Также советую почитать задание №9 на сайте http://www.123avr.com. Автор доступным языком объяснил все тонкости.
ADMUX=0xC9;
ADCSRA=0xE;
SFIOR&=0xEF;
Переходим к главной функции main(). Согласно алгоритма представленного на рисунке 8, после инициализации выводим заставку на LCD-дисплей, то есть вызываем функцию prompt(). Затем микроконтроллер должен в бесконечном цикле проверять буфер приемника USART и при обнаружении в нём команды типа «символ» выполняется соответствующее действие. Смотрим листинг кода:
void main(void)
{
init_avr();
#asm("sei")
prompt();
while (1)
{
switch (getchar())
case 'i':
putchar(252);
expectation();
break;
case 'p':
ADCSRA=0x8E;
TCCR0=0x03;
transfer();
break;
case 's':
TCCR0=0x00;
ADCSRA=0xE;
expectation();
break;
case 'l':
TCCR0=0x00;
ADCSRA=0xE;
TCNT0_value = 0x6;
break;
case 'n':
TCCR0=0x00;
ADCSRA=0xE;
TCNT0_value = 0x83;
break;
case 'f':
TCCR0=0x00;
ADCSRA=0xE;
TCNT0_value = 0xCE;
break;
case 't':
if (ADCSRA==0x8E)
{
TCCR0=0x00;
ADCSRA=0xE;
get_send_temp();
ADCSRA=0x8E;
TCCR0=0x03;
}
else
{
get_send_temp();
}
break;
}
}
На этом все. Компилируем код, заливаем hex в микроконтроллер, предварительно выставив fuse-биты на тактирование от внешнего кварцевого резонатора на частоте 8 МГц.
Литература:
Евстифеев А.В. Микроконтроллеры AVR семейства Mega. Руководство пользователя. – М.: Издательский дом «Додэка-XXI», 2007. – 592 c.: ил. (Серия «Программируемые системы»)
Интернет ресурс: http://www.123avr.com
P.S. В следующей части рассмотрим написание управляющей и анализирующей программы для ПК, написанной в среде MS Visual Studio на языке С#.
Рейтинг:  |
Просмотров: 51139 |
Нет комментариев.
 |
Гости не имеют права добавлять комментарии и проставлять рейтинг. |
|