Доброго дня. Помогите разрешить очередной затык на ровном месте при использовании WatchDog на Atmega8 с AVRStudio4.
СпойлерКод:
Код:
//Процедура задержки перед стартом основной программы void Wait_for_start(void) { //Мигаем индиатором WORK for (unsigned char i = 0; i < 25; i++) { //Мигаем индикатором WORK PORTB ^= (1 << PB0); //Пауза _delay_ms(50); //если закоментировать эту строку... //for (unsigned char i = 0; i < 255; i++) //...и раскомментировать эту и... // asm volatile ("nop"::); //...эту, то все работает
//Готовность к работе, READY в "1" PORTB |= (1 << PB3);
//Гасим индикатор WORK PORTB |= (1 << PB0); }
Настройка WatchDog
Код:
//Процедура инициализации WatchDog void init_WDT(void) { //Сброс таймера WatchDog asm volatile ("wdr"::); //Разрешение изменения режима работы WatchDog //и время ожидания сброса выставляем 2 с, WDTCR |= (1 << WDCE) | (1 << WDE) | (1 << WDP2) | (1 << WDP1) | (1 << WDP0); //Конец записи изменений WDTCR &= ~(1 << WDCE); }
Если пользоваться _delay_ms, то контроллер перезагружается, как будто строки со сбросом дальше нет. Если _delay_ms убрать, то все ок. WatchDog настроен на 2 с, т.е. задержка в десятки мс не должна влиять. Еще один нюанс: при загрузке программы с _delay_ms в протеус, все прекрасно работает (сообщений о ресете нет), но при заливке в реальную микросхему получаются только сплошные перезагрузки. Почему _delay_ms так влияет на сброс WatchDog?
_________________ We do what we must because we can (c) GLaDOS
я настоятельно рекомендую не изобретать велосипеды по настройке и сбросу WDT, а использовать "библиотечный", входящий в комплект WinAVR, вариант.
1. приинклюдить модуль <avr/wdt.h> 2. использовать для сброса WDT макрос wdt_reset(); 3. для настройки режима WDT использовать макрос wdt_enable() передавая ему в качестве параметра нужную константу WDTO_XXX
по всей видимости у вас режим WDT настроен некорректно
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
for (unsigned char i = 0; ... - попробуйте объявить i как volatile и посмотрите, что будет. Если начнет перезагружаться так же, как и с _delay_ms, то, скорее всего, строжевой таймер настроен некорректно.
_________________ Разница между теорией и практикой на практике гораздо больше, чем в теории.
Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.
я настоятельно рекомендую не изобретать велосипеды по настройке и сбросу WDT, а использовать "библиотечный", входящий в комплект WinAVR, вариант.
1. приинклюдить модуль <avr/wdt.h> 2. использовать для сброса WDT макрос wdt_reset(); 3. для настройки режима WDT использовать макрос wdt_enable() передавая ему в качестве параметра нужную константу WDTO_XXX
по всей видимости у вас режим WDT настроен некорректно
Спасибо, "библиотечно" работает.
YS писал(а):
F_CPU определен?
for (unsigned char i = 0; ... - попробуйте объявить i как volatile и посмотрите, что будет. Если начнет перезагружаться так же, как и с _delay_ms, то, скорее всего, строжевой таймер настроен некорректно. F_CPU определен?
for (unsigned char i = 0; ... - попробуйте объявить i как volatile и посмотрите, что будет. Если начнет перезагружаться так же, как и с _delay_ms, то, скорее всего, строжевой таймер настроен некорректно.
Частота определена в опциях проекта AVRStudio, в тексте программы F_CPU не опеределен. Но ковырять, что в моем варианте не пашет лень (watchdog в этой железке для душевного спокойствия, без явной необходимости), поюзаю библиотеку
_________________ We do what we must because we can (c) GLaDOS
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Доброе время суток. Может кто из знающих подскажет. Есть устройство на Amega8A при нажатии на определенную кнопку активирует выход (на пине порта B появляется +5В) на определенный интервал времени. И есть отдельная кнопка которая активирует (должна) выход постоянно, код для нее реализован на бесконечном цикле. Сброс всех временных установок осуществляется кнопкой "RESET" т.е. аппаратным сбросом контроллера, отключение выхода и возврат к состоянию ожидания нажатия какой либо кнопки. В Atmel Studio7 все работает как часы. Зашил контроллер, кнопки которые отсчитывают время работают нормально, а при нажатии кнопки для непрерывного режима через какое-то время выход отключается. Сторожевой таймер отключен. Может при реализации бесконечного цикла именно в "железе" есть какие-то засады? Бесконечный цикл завязанный сам на себя при помощи команды RJMP.
rjmp reset ;вектора прерываний nop ;rjmp INT0;External Interrupt Request 0 nop; rjmp INT1; External Interrupt Request 1 nop ;rjmp OC2; Timer/Counter2 Compare Match nop ;rjmp OVF; Timer/Counter2 Overflow nop ;rjmp ICP1; Timer/Counter1 Capture Event rjmp stop1; OC1A; Timer/Counter1 Compare Match A nop;rjmp OC1B; Timer/Counter1 Compare Match B nop; OVF1; Timer/Counter1 Overflow nop ;rjmp OVF0; Timer/Counter0 Overflow nop ;rjmp SPI; Serial Transfer Complete nop ;rjmp URXC; USART, Rx Complete nop ;rjmp UDRE; USART Data Register Empty nop ;rjmp UTXC; USART, Tx Complete nop ;rjmp ADCC; ADC Conversion Complete nop ;rjmp ERDY; EEPROM Ready nop ;rjmp ACI; Analog Comparator nop ;rjmp TWI; 2-wire Serial Interface nop ;rjmp SPMR; Store Program Memory Ready
reti
start: ldi r16,0b00000000; out ddrd,r16 ldi r16,0b11111111 out portd,r16 ldi r17,0b00000001 out ddrb,r17 ldi r17,0b00000000 out portb,r17 ;sbi portb,0 ldi r21,0b00000001
; ++++++++++++++++++++++++++++++++++++= начало циклов проверки сост кнопок замыкающихся на 0
switch: .def rin=r18; ldi rin,0b11111111 nop in rin,pind
init: ldi r19,0b00001100 out tccr1b,r19 ldi r19,0b00000000 out tccr1a,r19
;++++++++++++++++++++++отключение сторож таймера +++++++++++++++++++++++ ; ldi r20,0b00011000 ; out wdtcr,r20 ; nop ; ldi r20,0b00010000 ; out wdtcr,r20
; ++++++++++++++++++++++++++++ определение маски прерывания ++++++++++++++++++ ldi r20,0b00010000 out timsk,r20 sei
sbrc rin,0 rjmp sw1 out portb,r21 .equ kdel=1152 ldi r19,high(kdel) out ocr1ah,r19 ldi r19,low(kdel) out ocr1al,r19 out tcnt1h,r17 out tcnt1l,r17 c1: rjmp c1
sw1: sbrc rin,1 rjmp sw2 out portb,r21 .equ kdel1=2944 ldi r19,high(kdel1) out ocr1ah,r19 ldi r19,low(kdel1) out ocr1al,r19 out tcnt1h,r17 out tcnt1l,r17 c2: rjmp c2
sw2: sbrc rin,2 rjmp sw3 out portb,r21 .equ kdel2=6400 ldi r19,high(kdel2) out ocr1ah,r19 ldi r19,low(kdel2) out ocr1al,r19 out tcnt1h,r17 out tcnt1l,r17 c3: rjmp c3
sw3: sbrc rin,3 rjmp sw4 out portb,r21 .equ kdel3=7040 ldi r19,high(kdel3) out ocr1ah,r19 ldi r19,low(kdel3) out ocr1al,r19 out tcnt1h,r17 out tcnt1l,r17 c4: rjmp c4
sw4: sbrc rin,4 rjmp sw5 out portb,r21 .equ kdel4=10240 ldi r19,high(kdel4) out ocr1ah,r19 ldi r19,low(kdel4) out ocr1al,r19 out tcnt1h,r17 out tcnt1l,r17 c5: rjmp c5
;++++++++++++++++++++++++++++++++++++++++++++++++++++++ проверка состояния кнопки 5 (ВРЕМЕННО)
sw5: sbrc rin,5 rjmp sw6 out portb,r21 in rin,pind sbrc rin,5 rjmp stop1 rjmp sw5
;++++++++++++++++++++++++++++++++++++++++++++++++ проверка состояния кнопки 6 (НЕПРЕРЫВНО)
sw6: sbrc rin,6 rjmp switch sw66: out portb,r21 rjmp sw66
;#################КНОпка RESET начинает исполнение кода заново
stop1: cbi portb,0; установка пина b0 в 0 остальные в 0 откл нагрузки rjmp switch; переход на циклы проверки сост кн
Еще раз повторюсь сброс всего и откл нагрузки по кнопке RESET
Читал даташит, если я правильно понял, чтобы отключить сторож таймер надо во фьюзах WDTON поставить в 1 ?
вроде бы понял от чего идет прерывание по переполнению таймера 1, сейчас буду код ковырять. Хотя не понятно с чего вдруг, у меня стоит прерывание по сравнению на предыдущих кнопках.
Так это не Ваш код??? Если да, проще начать снова: -инициализация -опрос кнопок -если нажата кнопка на PD6 вывод 1 на PB0 -пока нажата кнопка на PD5 вывод 1 на PB0 -если нажата какая-то другая кнопка установить соответствующий интервал в OCR1A, выдать 1 на PB0 и запустить таймер; в прерывании сбросить PB0
Код мой. Решил проблему установкой команды запрещения прерываний перед опросом пина PD6, чтобы не было прерывания по переполнению таймера 1. Спасибо про замечание по поводу выхода из прерывания, это и послужило зацепкой. Заодно и стек инициализировал.
Здравствуйте. Хотел бы у вас спросить информацию. имею я программу, ватчдог и прерывание. В конце программы указан сон. Если я не ошибаюсь то программа будет выполняться следующем способов 1. Программа запускается и выполняется полностью 2. Во время выполнения "заводиться" ватчдог на режим прерывание на 8 секунд 3. в конце подулем sleep.h уходит спать
Через 8 секунд ватчдог выполнит только прерывание, или же и прерывание и основной код программы ? Мне хотелось бы что-бы только прерывание в конце которого будет комманда сон. Заранее большое спасибо
И в этот код я засовываю тоже самое что и в while(1) и в конце снова слип.
или вы выражаетесь не понятно, или я слишком туп, чтобы вас понять... общая канва вашей программы должна быть такой:
Код:
interrupt [WDT] void wdt_timeout_isr(void){ // тут только то, что должно работать по прерыванию от WDT и ничего более }
int main(void){ // тут не нужно никаких циклов, // делаете только то, что должно делаться ОДИН раз // после включения питания // а в самом конце - sleep в цикле
while(1) sleep(); }
и все. когда дойдет до последнего цикла - уснет. после просыпа отработает прерывание и "начало цикла" while(1), после чего снова уснет. и так далее до полного удовлетворения.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
И в этот код я засовываю тоже самое что и в while(1) и в конце снова слип.
или вы выражаетесь не понятно, или я слишком туп, чтобы вас понять... общая канва вашей программы должна быть такой:
Код:
interrupt [WDT] void wdt_timeout_isr(void){ // тут только то, что должно работать по прерыванию от WDT и ничего более }
int main(void){ // тут не нужно никаких циклов, // делаете только то, что должно делаться ОДИН раз // после включения питания // а в самом конце - sleep в цикле
while(1) sleep(); }
и все. когда дойдет до последнего цикла - уснет. после просыпа отработает прерывание и "начало цикла" while(1), после чего снова уснет. и так далее до полного удовлетворения.
Во - спасибо. Я думал помимо прерывания, цикла while он запустит вообще всю программу с нуля. Большое вам спасибо
Сейчас этот форум просматривают: metan, veso74 и гости: 21
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения