Ðналого цифровой преобразователь, таймер и Ð¸Ð½Ð´Ð¸ÐºÐ°Ñ†Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· 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 раз в секунду; | ||
- | } |