Аналого цифровой преобразователь, таймер и индикация через SPI

Материал из Automata.

(Различия между версиями)
Перейти к: навигация, поиск
м (Новая: #include <stdint.h> #include <avr/io.h> #include <avr/interrupt.h> #define GreenLed 0x10//закрепляем за GreenLed значение, равное 0х10; #define RedLed 0x...)
м (Полностью удалено содержимое страницы)
Строка 1: Строка 1:
-
#include <stdint.h>
 
-
#include <avr/io.h>
 
-
#include <avr/interrupt.h>
 
-
#define GreenLed 0x10//закрепляем за GreenLed значение, равное 0х10;
 
-
#define RedLed 0x40//закрепляем за RedLed значение, равное 0х40;
 
- 
-
//массив кодированных символов для отабражения на индикаторах;
 
-
static const uint8_t LEDS[10] = { 0x5f, 0x42, 0x37, 0x76 ,0x6a, 0x7c, 0x7d, 0x46, 0x7f, 0x7e };// 0, 1, ... 9;
 
-
static volatile uint8_t counts[3] = { 0, 0, 0 };//массив хранения значений разрядов числа для отображения;
 
-
static volatile uint8_t times[3] = { 0, 0, 0 };//массив хранения значений разрядов времени;
 
-
static volatile uint8_t time;//переменная, хранящая прошедшее с момента включения время;
 
- 
-
//функция отображения числа на индикаторах;
 
-
void IndicateLed(uint16_t num, uint8_t pin)
 
-
{
 
-
register uint8_t j;//переменная - счетчик;
 
-
//получение значений разрядов отображаемого числа для индексации в массиве LEDS[];
 
-
counts[2] = num % 10;
 
-
num /= 10;
 
-
counts[1] = num % 10;
 
-
num /= 10;
 
-
counts[0] = num % 10;
 
-
num /= 10;
 
-
SPCR |= _BV(SPE);//включаем модуль SPI;
 
-
for (j = 0; j < 3; j++) {//для каждой из отображаемых цифр;
 
-
uint8_t digit = counts[j];//берем соответствующую цифру;
 
-
SPDR = 0xff - LEDS[digit];//и отправляем ее инвертированный код в буфер SPI;
 
-
while (!(SPSR & _BV(SPIF)));//ждем окончания передачи;
 
-
}
 
-
SPCR &= ~_BV(SPE);//выключаем модуль SPI;
 
-
//защелкиваем в схеме индикаторов отправленное туда значение;
 
-
PORTB |= pin;
 
-
PORTB &= ~pin;
 
-
}
 
- 
-
//функция пересчета времени;
 
-
uint8_t TimeCount (void)
 
-
{
 
-
if (++times[2] > 9) {//увеличивая значение младшего разряда, проверяем его на превышение 9-ти;
 
-
times[2] = 0;//если превысел - обнуляем;
 
-
if (++times[1] > 5) {//увеличивая значение среднего разряда, проверяем его на превышение 5-ти;
 
-
times[1] = 0;//если превысел - обнуляем (в минуте - 60с);
 
-
if (++times[0] > 9)//увеличивая значение младшего разряда, проверяем его на превышение 9-ти;
 
-
times[0] = 0;//если превысел - обнуляем;
 
-
}
 
-
}
 
-
//возвращаем время для отображения;
 
-
return (times[0] * 100 + times[1] * 10 + times[2]);
 
-
}
 
-
 
-
//обработчик прерывания от первого таймера;
 
-
ISR (TIMER1_COMPA_vect)//по достижении счета числа, записанного в OCR1A;
 
-
{
 
-
time = TimeCount();//пересчитываем время;
 
-
}
 
- 
-
//обработчик прерывания от первого таймера;
 
-
ISR (TIMER1_COMPB_vect)//по достижении счета числа, записанного в OCR1B;
 
-
{
 
-
ADCSRA |= _BV(ADSC);//запускаем АЦП;
 
-
}
 
- 
-
//обработчик прерывания от модуля АЦП;
 
-
ISR (SIG_ADC)//по завершению цикла преобразования;
 
-
{
 
-
IndicateLed(time, GreenLed);//отображаем время на первом индикаторе;
 
-
IndicateLed(ADCH * 2, RedLed);//отображаем напряжение на втором;
 
-
}
 
- 
-
//главная функция;
 
-
int main (void)
 
-
{
 
-
DDRB = 0xff;//порт В настраиваем на выход;
 
-
PORTB = 0x00;//отправляем на выводы логический "0";
 
-
SREG = 0x80;//глобальное разрешение прерываний;
 
-
ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(ADLAR) | 0x07;//внутреннее опорное напряжение в 2.56в,
 
-
//смещение влево данных в регистрах ADCL и ADCH,
 
-
//вход АЦП - PC7_ADC7;
 
-
ADCSRA = _BV(ADEN) | _BV(ADIE);//включаем модуль АЦП и разрешаем прерывания от него;
 
-
SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR1);//включаем модуль SPI,
 
-
//настраиваем контроллер как Master - устройство,
 
-
//задаем предделитель в 64;
 
-
TCCR1B = _BV(WGM12) | _BV(CS12);//настраиваем таймер в режим CTC - "сброс при совпадении",
 
-
//задаем предделитель в 256;
 
-
TIMSK = _BV(OCIE1A) | _BV(OCIE1B);//разрешаем прерывания от первого таймера при совпадении значения
 
-
//в его счетном регистре TCNT1 со значением в регистрах OCR1A или OCR1B;
 
-
OCR1A = 31250;//8000000 / 256 = 31250, т.е. прерывания по совпадению с OCR1A будут происходить точно раз в секунду;
 
-
OCR1B = 6250;//31250 / 6250 = 5, т.е. модуль АЦП будет запускаться 5 раз в секунду;
 
-
}
 

Версия 13:04, 9 февраля 2010

Личные инструменты
Микроконтроллеры