В этой статье мы рассмотрим схему простого будильника на микроконтроллере ATmega32 (семейство AVR). Для реализации этой идеи мы используем 16 битный таймер, присутствующий в данном микроконтроллере.
Все цифровые часы имеют в своем составе кварцевый резонатор, который является их «сердцем». Кварцевые резонаторы присутствуют практически во всех системах реального времени. Подобные резонаторы генерируют временные импульсы, которые необходимы для точного вычисления времени. Существуют и другие способы точного задания временных интервалов, но все таки использование кварцевых резонаторов является наиболее предпочтительным для решения этой задачи. Поэтому и мы в рассматриваемой схеме будем подсоединять кварцевый резонатор к микроконтроллеру ATmega32 чтобы обеспечить точный расчет временных интервалов.
Необходимые компоненты
Аппаратное обеспечение
- Микроконтроллер ATmega32 (купить на AliExpress).
- Программатор AVR-ISP (купить на AliExpress), USBASP (купить на AliExpress) или другой подобный.
- JHD_162ALCD (ЖК дисплей 16×2) (купить на AliExpress).
- Кварцевый резонатор 11.0592 МГц.
- Конденсатор 22 пФ (2 шт.) (купить на AliExpress).
- Конденсатор 100 нФ (4 шт.) (купить на AliExpress).
- Конденсатор 47 мкФ (соединенный по питанию) (купить на AliExpress).
- Кнопка (4 шт.).
- Трехконтактный переключатель (2 шт.).
- Транзистор 2N2222.
- Зуммер (купить на AliExpress).
- Резистор 10 кОм (6 шт.) (купить на AliExpress).
- Резистор 200 Ом (купить на AliExpress).
- Источник питания с напряжением 5 Вольт.
Реклама: ООО «АЛИБАБА.КОМ (РУ)» ИНН: 7703380158
Программное обеспечение
Atmel Studio версии 6.1 (или выше)
Progisp или flash magic (необязательно)
Работа схемы
Схема устройства приведена на следующем рисунке.
Для точного подсчета интервалов времени мы подсоединили к микроконтроллеру кварцевый резонатор на 11.0592 МГц. Теперь для того, чтобы отключить внутренний генератор микроконтроллера ATmega32 мы должны соответствующим образом сконфигурировать его «нижние» фьюзы (fuse bits). Но мы не должны трогать «верхние» фьюзы чтобы JTAG интерфейс микроконтроллера был доступен (активирован).
Чтобы сообщить микроконтроллеру о том, чтобы он отключил внутренний генератор и работал от внешнего кварцевого резонатора мы должны выполнить команду
LOW USE BYTE = 0xFF или 0b11111111.
В представленной схеме PORTB микроконтроллера ATmega32 соединен с портом данным жидкокристаллического (ЖК) дисплея. Если вы не хотите трогать фьюзы (FUSE BITS) микроконтроллера, то не используйте PORTC, поскольку PORTC содержит специальные функции (типы связи), которые можно деактивировать только с помощью изменения фьюзов.
В ЖК дисплее (если мы не хотим использовать черный цвет) можно задействовать только 14 его контактов: 8 контактов для передачи данных (7-14 или D0-D7), 2 контакта для подачи питания (1&2 или VSS&VDD или gnd&+5v), 3-й контакт для управления контрастностью, 3 контакта для управления (RS&RW&E).
В представленной схеме мы использовали только 2 контакта управления ЖК дисплея для лучшего понимания работы схемы. Бит контраста и READ/WRITE используются нечасто, поэтому они могут быть замкнуты на землю. Это обеспечивает ЖК дисплею максимальную контрастность и переводит его в режим чтения. Теперь нам всего лишь нужно контролировать контакты ENABLE и RS чтобы передавать на ЖК дисплей символы и данные. Также на нашем сайте вы можете прочитать более подробную статью о подключении ЖК дисплея к микроконтроллеру AVR ATmega32.
В схеме необходимо сделать следующие соединения с ЖК дисплеем:
PIN1 или VSS — земля
PIN2 или VDD или VCC — +5v питание
PIN3 или VEE — земля (обеспечивает максимальный контраст ЖК дисплею)
PIN4 или RS (Register Selection) – контакт PD6 микроконтроллера
PIN5 или RW (Read/Write) — земля (переводит ЖК дисплей в режим чтения что упрощает взаимодействие с ним для начинающих)
PIN6 или E (Enable) — контакт PD5 микроконтроллера
PIN7 или D0 — контакт PB0 микроконтроллера
PIN8 или D1 — контакт PB1 микроконтроллера
PIN9 или D2 — контакт PB2 микроконтроллера
PIN10 или D3 — контакт PB3 микроконтроллера
PIN11 или D4 — контакт PB4 микроконтроллера
PIN12 или D5 — контакт PB5 микроконтроллера
PIN13 или D6 — контакт PB6 микроконтроллера
PIN14 или D7 — контакт PB7 микроконтроллера
В схеме мы использовали 8-битную связь (D0-D7) ЖК дисплея с микроконтроллером, хотя можно было ограничиться и 4-битной – но в этом случае код программы стал бы немного сложнее. Таким образом, мы использовали 10 контактов ЖК дисплея, 8 из которых будут использоваться для передачи данных и 2 для управления.
Первый переключатель в схеме используется для переключения между режимами часов и будильника. Если на контакте низкий уровень, мы можем настраивать время срабатывания будильника при помощи нажатия кнопок, присутствующих в схеме. Если на контакте высокий уровень, то с помощью кнопок мы настраиваем текущее время (время часов). Первая кнопка на схеме предназначена для инкрементирования минут, вторая – для декрементирования минут, третья – для инкрементирования часов, четвертая – для декрементирования часов.
Конденсаторы, включенные параллельно кнопкам, предназначены для устранения эффектов биений, возникающих при нажатии кнопок. Если их устранить, то однократное нажатие кнопок будут иногда распознаваться микроконтроллером как многократные. Резисторы, подсоединенные к выводам микроконтроллера, предназначены для ограничения тока при нажатии кнопок.
Если кнопка нажата, то на соответствующий контакт микроконтроллера подается «земля» и таким образом микроконтроллер распознает нажатие кнопки и предпринимает соответствующие действия
Перед началом написания программы для микроконтроллера мы должны правильным образом настроить регистры таймера для обеспечения точного подсчета временных интервалов. Частота кварцевого резонатора у нас 11059200 Гц, если мы разделим ее на 1024, то получим 10800. Таким образом, для каждой секунды мы будем иметь 10800 импульсов. Поэтому мы должны использовать коэффициент деления предделителя равный 1024 чтобы получить частоту счетного регистра равную 10800 Гц. Для подсчета времени мы будем использовать 16 битный таймер микроконтроллера ATmega32. Данный таймер способен использовать функцию сравнения, которая заключается в непрерывном (каждый машинный цикл) сравнении содержимого счетного регистра таймера/счетчика с числом, находящемся в регистре сравнения. При совпадении содержимого этих регистров устанавливается флаг соответствующего прерывания, а также могут выполняться другие действия.
Поскольку в регистр сравнения мы будем записывать число 10800 это значит что с высокой точностью у нас каждую секунду будет генерироваться прерывание от таймера – это обстоятельство мы можем использовать для точного подсчета времени.
Рассмотрим теперь необходимую нам конфигурацию регистров таймера.
BROWN (коричневый, WGM10-WGM13): эти биты задают режим функционирования таймера в соответствии с нижеприведенной таблицей.
Поскольку мы будем использовать режим сравнения (режим CTC — Clear Timer Counter) значения таймера с числом, находящимся в байте OCR1A, мы должны установить WGM12 в 1, а остальные эти биты не трогать (по умолчанию в них при инициализации микроконтроллера записывается 0).
RED (красный, CS10,CS11,CS12): эти биты используются для задания коэффициента деления предделителя и соответствующего конфигурирования счетного регистра (установки частоты его работы).
Поскольку мы будем использовать коэффициент деления предделителя равный 1024 мы должны установить CS12 и CS10 в 1.
Другой регистр, который потребуется нам для написания программы – это TIMSK (регистр маски прерываний от таймеров, осуществляет разрешение/запрещение прерываний от таймера).
GREEN (зеленый, OCIE1A): этот бит должен быть установлен для разрешения прерывания при совпадении значения счетного регистра с числом, хранящимся в OCR1A (мы будем записывать туда число 10800).
Исходный код программы на языке С (Си) с пояснениями
Программа для рассматриваемой нами схемы будильника на микроконтроллере AVR ATmega32 представлена следующим фрагментом кода на языке С (Си). Комментарии к коду программу поясняют принцип работы отдельных команд.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
#include <avr/io.h> // заголовок чтобы задействовать контроль данных на контактах #define F_CPU 1000000 // задание тактовой частоты микроконтроллера #include <util/delay.h> // заголовок чтобы задействовать функции задержки в программе #define E 5 // задействуем 5-й контакт PORTD (“enable”), поскольку он соединен с контактом “enable” ЖК дисплея #define RS 6 // задействуем выбор регистра (“registerselection”) на 6-м контакте PORTD, поскольку он соединен с контактом RS ЖК дисплея void send_a_command(unsigned char command); void send_a_character(unsigned char character); void send_a_string(char *string_of_characters); ISR(TIMER1_COMPA_vect); static volatile int SEC =0;//переменная для хранения числа секунд static volatile int MIN =0;// переменная для хранения числа минут static volatile int HOU =0;// переменная для хранения числа часов int main(void) { DDRA = 0b11000000;// устанавливаем на вывод только pin7 и pin8 порта A DDRD = 0xFF; // порт D конфигурием на вывод данных _delay_ms(50);//задержка 50ms DDRB = 00FF;//устанавливаем portB на вывод данных TCCR1B |=(1<<CS12)|(1<<CS10)|(1<<WGM12); // устанавливаем предделитель и режим CTC (режим сравнения) OCR1A=10800;//записываем в OCR1A число 10800 чтобы получать точно каждую секунду прерывание от таймера sei();// общее разрешение прерываний TIMSK |=(1<<OCIE1A);//разрешаем прерывание в режиме сравнения char SHOWSEC [2];//символьный массив для отображения секунд на экране ЖК дисплея char SHOWMIN [2];// символьный массив для отображения минут на экране ЖК дисплея char SHOWHOU [2];// символьный массив для отображения часов на экране ЖК дисплея int ALSEC = 0;//переменная для хранения числа секунд будильника int ALMIN = 0;// переменная для хранения числа минут будильника int ALHOU = 0;// переменная для хранения числа часов будильника char SHOWALSEC [2];// символьный массив для отображения секунд будильника на экране ЖК дисплея char SHOWALMIN [2];// символьный массив для отображения минут будильника на экране ЖК дисплея char SHOWALHOU [2];// символьный массив для отображения часов будильника на экране ЖК дисплея send_a_command(0x01); //очистить экран 0x01 = 00000001 _delay_ms(50); send_a_command(0x38);// сообщаем ЖК дисплею что мы будем использовать 8 битный режим передачи данных/команд _delay_ms(50); send_a_command(0b00001111);// включаем курсор и мигание курсора на ЖК дисплее while(1) { itoa(HOU/10,SHOWHOU,10); //преобразование целого числа (десятичной части числа часов) в строку, 10 – десятичная система счисления send_a_string(SHOWHOU);// отображение на ЖК дисплее числа часов // отображение десятичной части числа часов (первого разряда числа часов) itoa(HOU%10,SHOWHOU,10); send_a_string(SHOWHOU); // отображение единичной части числа часов (второго разряда числа часов) send_a_string (":");//отображение символа ":" send_a_command(0x80 + 3);// переводим курсор на 4 позицию itoa(MIN/10,SHOWMIN,10); //преобразование целого числа (десятичной части числа минут) в строку, 10 – десятичная система счисления send_a_string(SHOWMIN); // отображение десятичной части числа минут (первого разряда числа минут) itoa(MIN%10,SHOWMIN,10); send_a_string(SHOWMIN); // отображение единичной части числа минут (первого разряда числа минут) send_a_command(0x80 + 5); // переводим курсор на 6 позицию send_a_string (":"); send_a_command(0x80 + 6);// переводим курсор на 7 позицию if (bit_is_set(PINA,5)) // если на контакте будильника высокий уровень { send_a_string(" ALM:ON "); //отображение строки (" ALM:ON " if ((ALHOU==HOU)&(ALMIN==MIN)&(ALSEC==SEC))//alarm minute=min //and alarm hours= time hours and alarm seconds= time seconds – сравнение времени будильника со значением часов { PORTA|=(1<<PINB7);//включаем звонок } } if (bit_is_clear(PINA,5))// если на контакте будильника низкий уровень { send_a_string(" ALM:OFF");//показываем строку что будильник отключен PORTA&=~(1<<PINB7);//выключаем звонок } send_a_command(0x80 + 0x40 + 0);// перемещаем курсор на нулевую позицию 2 строки send_a_string ("ALARM:");//отображение строки "ALARM:" send_a_command(0x80 + 0x40 + 7);// перемещаем курсор на восьмую позицию 2 строки // отображение числа часов itoa(ALHOU/10,SHOWALHOU,10); send_a_string(SHOWALHOU); itoa(ALHOU%10,SHOWALHOU,10); send_a_string(SHOWALHOU); send_a_command(0x80 + 0x40 +9); send_a_string (":"); send_a_command(0x80 + 0x40 +10); // отображение числа минут itoa(ALMIN/10,SHOWALMIN,10); send_a_string(SHOWALMIN); itoa(ALMIN%10,SHOWALMIN,10); send_a_string(SHOWALMIN); send_a_command(0x80 + 0x40+ 12); send_a_string (":"); send_a_command(0x80 + 0x40+ 13); // отображение числа секунд itoa(ALSEC/10,SHOWALSEC,10); send_a_string(SHOWALSEC); itoa(ALSEC%10,SHOWALSEC,10); send_a_string(SHOWALSEC); send_a_command(0x80 + 0); send_a_command(0x80 + 0);// перемещаем курсор на нулевую позицию if (bit_is_set(PINA,4)) // если переключатель установлен в положение настройки времени { if (bit_is_clear(PINA,0)) //если кнопка 1 нажата { if (MIN<60) { MIN++;// если число минут меньше 60 то инкрементировать число минут на 1 _delay_ms(220); } if (MIN==60) { if (HOU<24) { HOU++;// если число минут=60, кнопка нажата и число часов меньше 24, то инкрементировать число минут на 1 } MIN=0;// если число минут=60 то обнулить число минут _delay_ms(220); } } if (bit_is_clear(PINA,1)) { if (MIN>0) { MIN--; // если вторая кнопка нажата и число минут больше 0, то уменьшить число минут на 1 _delay_ms(220); } } if (bit_is_clear(PINA,2)) { if (HOU<24) { HOU++; //если третья кнопка нажата и число часов меньше 24, то увеличить число часов на 1 } _delay_ms(220); if (HOU==24) { HOU=0;//если число часов равно 24, то обнулить число часов } } if (bit_is_clear(PINA,3)) { if (HOU>0) { HOU--;//если четвертая кнопка нажата и число часов больше 0, то уменьшить число часов на 1 _delay_ms(220); } } } if (bit_is_clear(PINA,4))//если выбран режим настройки будильника { if (bit_is_clear(PINA,0)) { if (ALMIN<60) { ALMIN++; _delay_ms(220); } if (ALMIN==60) { if (ALHOU<24) { ALHOU++; } ALMIN=0; _delay_ms(220); } } if (bit_is_clear(PINA,1)) { if (ALMIN>0) { ALMIN--; _delay_ms(220); } } if (bit_is_clear(PINA,2)) { if (ALHOU<24) { ALHOU++; } _delay_ms(220); if (ALHOU==24) { ALHOU=0; } } if (bit_is_clear(PINA,3)) { if (ALHOU>0) { ALHOU--; _delay_ms(220); } } } } } // все то же самое, только теперь для режима настройки времени ISR(TIMER1_COMPA_vect) //цикл который выполняется до тех пор пока значения в таймере не будет равно сравниваемому значению { if (SEC<60) {SEC++;} if (SEC==60) { if (MIN<60) {MIN++;} SEC=0; } if (MIN==60) { if (HOU<24) {HOU++;} MIN=0; } if (HOU==24) {HOU=0;} } void send_a_command(unsigned char command) { PORTA = command; PORTD &= ~ (1<<RS); // устанавливаем RS в 0 чтобы сообщить ЖК дисплею что мы будем передавать команду PORTD |= 1<<E; // сообщаем ЖК дисплею чтобы он принял команду/данные _delay_ms(50); PORTD &= ~1<<E;// сообщаем ЖК дисплею что мы закончили передачу данных PORTA= 0; } void send_a_character(unsigned char character) { PORTA= character; PORTD |= 1<<RS;// сообщаем ЖК дисплею что мы будем передавать данные (не команду) PORTD |= 1<<E;// сообщаем ЖК дисплею чтобы он начал прием данных _delay_ms(50); PORTD &= ~1<<E;// сообщаем ЖК дисплею что мы закончили передачу данных PORTA = 0; } void send_a_string(char *string_of_characters) { while(*string_of_characters > 0) { send_a_character(*string_of_characters++); } } |
Теперь код программы без комментариев.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
/* ---- Code for Digital Clock with Alarm using AVR Microcontroller ------ */ #include <avr/io.h> #define F_CPU 11059200 #include <util/delay.h> #include <stdlib.h> #include <avr/interrupt.h> #define enable 5 #define registerselection 6 void send_a_command(unsigned char command); void send_a_character(unsigned char character); void send_a_string(char *string_of_characters); ISR(TIMER1_COMPA_vect); static volatile int SEC =0; static volatile int MIN =0; static volatile int HOU =0; int main(void) { DDRA = 0b11000000; DDRB = 0xFF; DDRD = 0xFF; TCCR1B |=(1<<CS12)|(1<<CS10)|(1<<WGM12); OCR1A=10800; sei(); TIMSK |=(1<<OCIE1A); char SHOWSEC [2]; char SHOWMIN [2]; char SHOWHOU [2]; int ALSEC = 0; int ALMIN = 0; int ALHOU = 0; char SHOWALSEC [2]; char SHOWALMIN [2]; char SHOWALHOU [2]; send_a_command(0x01); //Clear Screen 0x01 = 00000001 _delay_ms(50); send_a_command(0x38); _delay_ms(50); send_a_command(0b00001111); _delay_ms(50); while(1) { itoa(HOU/10,SHOWHOU,10); send_a_string(SHOWHOU); itoa(HOU%10,SHOWHOU,10); send_a_string(SHOWHOU); send_a_string (":"); send_a_command(0x80 + 3); itoa(MIN/10,SHOWMIN,10); send_a_string(SHOWMIN); itoa(MIN%10,SHOWMIN,10); send_a_string(SHOWMIN); send_a_command(0x80 + 5); send_a_string (":"); send_a_command(0x80 + 6); itoa(SEC/10,SHOWSEC,10); send_a_string(SHOWSEC); itoa(SEC%10,SHOWSEC,10); send_a_string(SHOWSEC); if (bit_is_set(PINA,5)) { send_a_string(" ALM:ON "); if ((ALHOU==HOU)&(ALMIN==MIN)&(ALSEC==SEC)) { PORTA|=(1<<PINB7); } } if (bit_is_clear(PINA,5)) { send_a_string(" ALM:OFF"); PORTA&=~(1<<PINB7); } send_a_command(0x80 + 0x40 + 0); send_a_string ("ALARM:"); send_a_command(0x80 + 0x40 + 7); itoa(ALHOU/10,SHOWALHOU,10); send_a_string(SHOWALHOU); itoa(ALHOU%10,SHOWALHOU,10); send_a_string(SHOWALHOU); send_a_command(0x80 + 0x40 +9); send_a_string (":"); send_a_command(0x80 + 0x40 +10); itoa(ALMIN/10,SHOWALMIN,10); send_a_string(SHOWALMIN); itoa(ALMIN%10,SHOWALMIN,10); send_a_string(SHOWALMIN); send_a_command(0x80 + 0x40+ 12); send_a_string (":"); send_a_command(0x80 + 0x40+ 13); itoa(ALSEC/10,SHOWALSEC,10); send_a_string(SHOWALSEC); itoa(ALSEC%10,SHOWALSEC,10); send_a_string(SHOWALSEC); send_a_command(0x80 + 0); if (bit_is_set(PINA,4)) { if (bit_is_clear(PINA,0)) { if (MIN<60) { MIN++; _delay_ms(220); } if (MIN==60) { if (HOU<24) { HOU++; } MIN=0; _delay_ms(220); } } if (bit_is_clear(PINA,1)) { if (MIN>0) { MIN--; _delay_ms(220); } } if (bit_is_clear(PINA,2)) { if (HOU<24) { HOU++; } _delay_ms(220); if (HOU==24) { HOU=0; } } if (bit_is_clear(PINA,3)) { if (HOU>0) { HOU--; _delay_ms(220); } } } if (bit_is_clear(PINA,4)) { if (bit_is_clear(PINA,0)) { if (ALMIN<60) { ALMIN++; _delay_ms(220); } if (ALMIN==60) { if (ALHOU<24) { ALHOU++; } ALMIN=0; _delay_ms(220); } } if (bit_is_clear(PINA,1)) { if (ALMIN>0) { ALMIN--; _delay_ms(220); } } if (bit_is_clear(PINA,2)) { if (ALHOU<24) { ALHOU++; } _delay_ms(220); if (ALHOU==24) { ALHOU=0; } } if (bit_is_clear(PINA,3)) { if (ALHOU>0) { ALHOU--; _delay_ms(220); } } } } } ISR(TIMER1_COMPA_vect) { if (SEC<60) { SEC++; } if (SEC==60) { if (MIN<60) { MIN++; } SEC=0; } if (MIN==60) { if (HOU<24) { HOU++; } MIN=0; } if (HOU==24) { HOU=0; } } void send_a_command(unsigned char command) { PORTB = command; PORTD &= ~ (1<<registerselection); PORTD |= 1<<enable; _delay_ms(3); PORTD &= ~1<<enable; PORTB = 0xFF; } void send_a_character(unsigned char character) { PORTB = character; PORTD |= 1<<registerselection; PORTD |= 1<<enable; _delay_ms(3); PORTD &= ~1<<enable; PORTB = 0xFF; } void send_a_string(char *string_of_characters) { while(*string_of_characters > 0) { send_a_character(*string_of_characters++); } } |
21 ответ к “Будильник на микроконтроллере AVR ATmega32”
Здравствуйте. Не имеется ли платы данного устройства, желательно в программе spring-layout, для дальнейшей ее печати?
Добрый вечер. К сожалению нет
Здравствуйте, можете объяснить как идет ток по схеме и что за чем идёт?
Добрый вечер, ток от чего к чему? На схеме просто достаточно много цепей прохождения тока
Какую программу можно использовать для программирования микроконтроллера?
Вот, посмотрите карту статей про микроконтроллеры AVR на нашем сайте, там есть отдельный раздел про программы
Здравствуйте, Конденсатор 47 мкФ с чем должен соединяться и для чего он нужен в схеме?
Добрый вечер. Это просто фильтрующий конденсатор по питанию, фильтрует/сглаживает нежелательные выбросы напряжения. Одним концом подключается к питанию, а другим — к общему проводу
А есть схема работы этого будильника, в proteus?
Скажите пожалуйста, как я могу транслировать из языка с в язык ассемблера, какую программу использовать?
К сожалению, я такой программы не знаю
И еще вопрос, блок питания тут 5В, а ток я понимаю тут 1-1,5А?
Да, питание 5В, а в какой части схемы вы такой огромный ток ожидаете увидеть? Микроконтроллер от такого тока просто сгорит. Максимальный ток здесь может только через транзистор течь если зуммер мощный поставить, но, согласно ТТХ, максимальный ток через транзистор 2N2222 может составлять 0.6 A, но никак не 1-1,5А
И еще один вопрос(не злитесь), куда писать это LOW USE BYTE = 0xFF или 0b11111111.
Вначале функции int main(void) можно написать, в месте где задается направление работы портов ввода/вывода
Здравствуйте. А где видно, что Showsec, Showmin, Showhou и т. д. равны Sec, Min, How? Как в этом выражении: «itoa(HOU/10,SHOWHOU,10);» одно заменяется на другое и выводится на LCD? У меня вообще ничего в Протеусе не выводится.
Ну, смотрите, там же в программе ниже после команды itoa(HOU/10,SHOWHOU,10) есть и команды itoa(MIN/10,SHOWMIN,10), itoa(SEC/10,SHOWSEC,10). Или вы что то другое имели ввиду? Если программа целиком не запускается, то следует применить известный прием — пытаться запускать и отлаживать работу программы по частям. Эту программу достаточно просто же разбить на части, которые можно по отдельности протестировать
Нет, я имел в виду, что после первой скобки в выражении «itoa(min/…», а выводятся данные в виде массива showmin. Где происходит их замена? Или формула для itoa имеет какую-то стандартную запись и замена происходит автоматически?
Так функция itoa как раз и преобразует число min в массив символов showmin, которые затем выводятся на экран ЖК дисплея. Вы же число сами по себе просто так на ЖК дисплее не отобразите
Здравствуйте, а можно ли этот механизм поставить внутарь ламповых часов, а если нет, то какой можно?
Добрый вечер. Я думаю в чистом виде его внутрь ламповых часов не удастся поставить поскольку у выводов микроконтроллера не хватит тока чтобы управлять лампами. Нужно между выводами микроконтроллера и лампами поставить какие-нибудь переключатели, например, реле или транзисторы