aai_m 0 14 марта, 2008 Опубликовано 14 марта, 2008 · Жалоба Подобная тема поднималась уважаемым klen 16.11.2007 http://electronix.ru/forum/index.php?showt...%E0%E9%F2%E0%ED . К сожалению, проблема решена не была. Вернее уважаемый klen в частном случае решил, но сослася на потусторонние силы - "ШАЙТАН - БАЙРАМ" . Суть проблемы - по ходу работы программы необходимо останавливать и вновь запускать таймер Т3 и менять содержимое регистров OCR3A/OCR3B/TCNT3. Первичная инициализация Т3 проходит успешно: void timer3_init(void) { TCCR3B = 0x00; //stop TCNT3H = 0xC1; //setup TCNT3L = 0x81; OCR3AH = 0x07; OCR3AL = 0xCF; OCR3BH = 0x07; OCR3BL = 0xCF; OCR3CH = 0x07; OCR3CL = 0xCF; ICR3H = 0x07; ICR3L = 0xCF; TCCR3A = 0x00; TCCR3B = 0x09; //start Timer } Далее открываем фирменное описание на ATMEGA128 на странице 114 и читаем: "The TCNTn, OCRnA/B/C, and ICRn are 16-bit registers that can be accessed by the AVR CPU via the 8-bit data bus. The 16-bit register must be byte accessed using two read or write operations. Each 16-bit timer has a single 8-bit register for temporary storing of the high byte of the 16-bit access. ". Спасибо, что предупредили. Более того на странице 116 описания написано: "The following code examples show how to do an atomic write of the TCNTn Register contents. Writing any of the OCRnA/B/C or ICRn Registers can be done by using the same principle." И дается пример кода: TIM16_WriteTCNTn: ; Save global interrupt flag in r18,SREG ; Disable interrupts cli ; Set TCNTn to r17:r16 out TCNTnH,r17 out TCNTnL,r16 ; Restore global interrupt flag out SREG,r18 ret НО ЭТОТ КОД НИКОГДА РАБОТАТЬ НЕ БУДЕТ! Потому что, на странице 365 того же описания с изумлением читаем: ($89) TCNT3H Timer/Counter3 – Counter Register High Byte ($88) TCNT3L Timer/Counter3 – Counter Register Low Byte ($87) OCR3AH Timer/Counter3 – Output Compare Register A High Byte и т. д. Т. е. out TCNTnH,r17 в принципе не возможно(как к регистру ввода-вывода, т.к. такой регистр в регистровом файле отсутствует), а должно быть, по крайней мере, sts TCNTnH,R17 (как к адресному пространству памяти данных). Применяем вот такую функцию : void WriteOCR3A( unsigned int i ) { unsigned char sreg; CLI(); sreg = SREG; OCR3A = i; SREG = sreg; SEI(); } Но таймер Т3 правильно не настраивается. Причем есть действительно чертовчина. Например: TCCR3B = 0x00; //stop WriteTCNT3(Mem_TCNT); WriteOCR3A(Mem_D_Period); TCCR3B = 0x09; //start - не работает, TCCR3B = 0x00; //stop WriteTCNT3(Mem_TCNT); WriteOCR3С(Mem_D_Period); TCCR3B = 0x09; //start - не работает. В симуляторе AVRStudio(Version 4.14 Beta 2) все работает без проблем. Прошу помощи советом, ссылками для решения этой проблемы. Заранее благодарен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
hd44780 0 14 марта, 2008 Опубликовано 14 марта, 2008 · Жалоба out TCNTnH,r17 - обобщенный вид инструкций out TCNT0H,r17, out TCNT1H,r17 и т.д. по числу таймеров. Так что работать должно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aai_m 0 14 марта, 2008 Опубликовано 14 марта, 2008 · Жалоба out TCNTnH,r17 - обобщенный вид инструкций out TCNT0H,r17, out TCNT1H,r17 и т.д. по числу таймеров. Так что работать должно. Позвольте с Вами не согласиться. Дело в том, что команда out P,Rr допустима для операндов P и Rr, где P - порт(или регистр имеющий адрестр в регистровом файле), а Rr - регистр общего назначения. Так вот TCNT3H, TCNT3L и т.д. не находятся в регистровом файле, а доступны лишь как память данных. Т.Е. КОМАНДА OUT К НИМ НЕ ДОПУСТИМА. $2D ($4D) TCNT1H Timer/Counter1 – Counter Register High Byte $2C ($4C) TCNT1L Timer/Counter1 – Counter Register Low Byte Для TCNT1H таймера Т1 возможно out $2D, Rr или sts $4D, Rr но для таймера T3 ($89) TCNT3H Timer/Counter3 – Counter Register High Byte доступно долько sts $89, R. См. стр. 361, 362 описания 2467P–AVR–08/07 http://www.atmel.com/dyn/resources/prod_do...nts/doc2467.pdf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KRS 0 14 марта, 2008 Опубликовано 14 марта, 2008 · Жалоба Для TCNT1H таймера Т1 возможно out $2D, Rr или sts $4D, Rr но для таймера T3 Я для таких случаев написал макрос //************************************************************************** // OutPort - generate out or sts instruction OutPort MACRO Port,reg IF (Port)<0x40 OUT Port, reg ELSE STS Port, reg ENDIF ENDM Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aai_m 0 14 марта, 2008 Опубликовано 14 марта, 2008 · Жалоба Я для таких случаев написал макрос //************************************************************************** // OutPort - generate out or sts instruction OutPort MACRO Port,reg IF (Port)<0x40 OUT Port, reg ELSE STS Port, reg ENDIF ENDM Уважаемый KRS, спасибо за совет. Возьму на вооружение, но проблема в том, что 16 разрядные регистры таймера Т3 даже при правильном обращении STS ведут себя не адекватно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 14 марта, 2008 Опубликовано 14 марта, 2008 · Жалоба Спасибо, что предупредили. Более того на странице 116 описания написано: На самом деле это серьёзный плюс! Впервые такая конструкция была применена в i8054, так как в i8053 было сделано "обычно", в результате чего вы могли получить ошибку превышающую 256 единиц! НО ЭТОТ КОД НИКОГДА РАБОТАТЬ НЕ БУДЕТ! Потому что, на странице 365 того же описания с изумлением читаем... Да эта ошибка у них практически в каждом даташите, где появилось обращение к регистрам ч/з LD/ST. Так как вы применяете, я тоже применяю таймера. Никаких проблем не возникало никогда. AVR Studio отлично эмулирует и достаточно точно. Единственно, что AVR Studio неверно эмулирует это обращения по не верным адресам. Ну например сделали вы стэк в области адресов ввода/вывода (например там даже устройств нет), - а в AVR Studio всё прекрасно работает. А в кристалле - шиш. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Don_Ambrosio 0 14 марта, 2008 Опубликовано 14 марта, 2008 · Жалоба но проблема в том, что 16 разрядные регистры таймера Т3 даже при правильном обращении STS ведут себя не адекватно. о "граблях" когда когда долго мучился с "глюком", а в результате "сам дурак" оказался Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KRS 0 14 марта, 2008 Опубликовано 14 марта, 2008 · Жалоба Применяем вот такую функцию : void WriteOCR3A( unsigned int i ) { unsigned char sreg; CLI(); sreg = SREG; OCR3A = i; SREG = sreg; SEI(); } а зачем сохранять sreg? обычно всетки функция выгдядит так void WriteOCR3A( unsigned int i ) { unsigned char sreg; sreg = SREG; CLI(); OCR3A = i; SREG = sreg; } или под IAR это делается так unsigned char oldState; oldState = __save_interrupt(); __disable_interrupt(); /* Critical section goes here */ __restore_interrupt(oldState); Кроме того, если вы используете чтение/запись 16 разрядных регистров только в основном коде или только в прерывании можно не запрещать прерывания, потому что между записью/чтением первого байта и второго может пройти неограниченное время ( гглавное что бы не вклинилась другая операция доступа к 16 разрядному регистру этого же таймера) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aai_m 0 14 марта, 2008 Опубликовано 14 марта, 2008 (изменено) · Жалоба На самом деле это серьёзный плюс! Впервые такая конструкция была применена в i8054, так как в i8053 было сделано "обычно", в результате чего вы могли получить ошибку превышающую 256 единиц! Да эта ошибка у них практически в каждом даташите, где появилось обращение к регистрам ч/з LD/ST. Так как вы применяете, я тоже применяю таймера. Никаких проблем не возникало никогда. AVR Studio отлично эмулирует и достаточно точно. Единственно, что AVR Studio неверно эмулирует это обращения по не верным адресам. Ну например сделали вы стэк в области адресов ввода/вывода (например там даже устройств нет), - а в AVR Studio всё прекрасно работает. А в кристалле - шиш. :) Уважаемый SasaVitebsk, Вы можете, в качестве примера привести код при работе с таймером Т3 для MEGA128. Заранее благодарен. о "граблях" когда когда долго мучился с "глюком", а в результате "сам дурак" оказался Уважаемый Дон Амброзио, есть три опытных образца и все ведут себя одинаково. Правда MEGA128 из одной партии. Может быть. Не охота конечно демонтировать MEGA128. Уважаемый KRS, поначалу SREG не сохранял, но сохранять советует описание ATMEGA128. Но эффекта нет. Возможно предлагают сохранять SREG по такой причине: "2. Interrupts may be lost when writing the timer registers in the asynchronous timer If one of the timer registers which is synchronized to the asynchronous timer2 clock is written in the cycle before a overflow interrupt occurs, the interrupt may be lost." (Errata ATmega128 Rev. M) стр. 370. Изменено 14 марта, 2008 пользователем aai_m Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 14 марта, 2008 Опубликовано 14 марта, 2008 · Жалоба Уважаемый SasaVitebsk, Вы можете, в качестве примера привести код при работе с таймером Т3 для MEGA128. Заранее благодарен. Я не работал с м128. Но какая разница? Таймеры у них у всех один к одному и давно уже не меняются. Работал с м640/м2560 (вплоть до 5 включительно) и, недавно с at90can128 (применял программный ШИМ). Ну и как обычно м8/м4/м88/м16/м64. Что именно у вас не работает? Опишите по подробнее! c = UDR0; // Прочитать символ TCNT3 = -(TIMOUT485); // Начать сначала TIFR3 = TIFR3; TIMSK3 = 1; // Разрешить прерывания от Таймера 3 (Расчёт таймаута) ... #pragma vector=TIMER3_OVF_vect // Тайм-аут для 485 интерфейса. Время переключения 5мс __interrupt static void TimeOutFor485(void) { ... TIMSK3 = 0; // Запретить прерывания от таймера } ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться