_delay_ms() работает намного медленнее, чем ожидалось (в 6 раз) на tinyAVR 0/1 (ATTiny1604)
Я разработал специальную плату разработки AVR с использованием микроконтроллера Atmel ATTiny1604. Он принадлежит к новому семейству Tiny-0, из-за его недавности некоторые необходимые изменения в соответствующих цепочках инструментов еще не включены в стабильную версию (я предпочитаю использовать исходные восходящие цепочки инструментов вместо SDK Atmel / Microchip). Таким образом, я скомпилировал последние версии toolchains из исходных текстов. Они включают в себя ...
AVR GCC 10.2.0
avr-libc, магистраль svn, с примененным патчем
avrxmega3-v10.diff
После того, как я установил цепочки инструментов, я написал программу мигания светодиодов, чтобы проверить, правильно ли работает моя цепочка инструментов. Программа была собрана с помощью avr-gcc -mmcu=attiny1604 -Wall -Os -o blink.elf blink.c -Wl,--section-start=.text=0x200
и загружена через загрузчикOptiboot_X.
#define F_CPU 20000000UL
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
PORTB.DIRSET = 0b00000001;
while (1) {
PORTB.OUTSET = 0b00000001;
_delay_ms(500);
PORTB.OUTCLR = 0b00000001;
_delay_ms(500);
}
}
Однако я обнаружил, что _delay_ms(500)
работает не так, как ожидалось. Вместо задержки в 500 миллисекунд фактическая задержка ближе к 3000 миллисекунд, как видно на осциллографе, она была замедлена в 6 раз.
Я дважды проверил настройки своих предохранителей.
$ pyupdi -d tiny1604 -c /dev/ttyUSB0 -fr
Device info: {'family': 'tinyAVR', 'nvm': 'P:0', 'ocd': 'D:0', 'osc': '3', 'device_id': '1E9425', 'device_rev': '0.0'}
Fuse:Value
0:0x00
1:0x00
2:0x02
3:0xFF
4:0x00
5:0xF6
6:0x07
7:0x00
8:0x02
9:0xFF
10:0xC5
Я видел сообщение pyupdi о том, что предохранитель
OSCCFG
(№ 2) запрограммирован на значение 0x02
, что, согласно спецификации, означает "Работать на частоте 20 МГц с соответствующей заводской калибровкой". Почему я получаю неправильные задержки, даже когда системные часы работают с правильной скоростью? Моя цепочка инструментов сломана?
Примечание: Этот вопрос я уже решил. Но учитывая, что в Интернете относительно мало руководств по новому tinyAVR 0/1, я разместил вопрос и ответ здесь, чтобы служить справочником для сообщества.
@比尔盖子, 👍13
1 ответ
Лучший ответ:
Ваша цепочка инструментов не сломана. В техническом описании ATTiny804 / 1604, стр. 77, показано, что частота процессора отделена от частоты генератора 20/16 МГц с помощью прескалера (в техническом описании ATTiny1614 тот же прескалер тактовой частоты показан на стр. 80. Так что эта функция присутствует в обоих микроконтроллерах tinyAVR 0/1).
Источник: Спецификация микрочипа ATTiny804 / 1604, добросовестное использование.
В техническом описании сказано ...
10.3.3 Основные тактовые частоты после сброса После любого сброса
CLK_MAIN
обеспечивается генератором 16/20 МГц (OSC20M
) с коэффициентом деления прескалера, равным 6. Поскольку фактическая частотаOSC20M
определяется битами выбора частоты (FREQSEL
) предохранителя конфигурации генератора (FUSE.OSCCFG
), эти частоты возможны после сброса:
- 16 МГц ---> 2,66 МГц
- 20 МГц ---> 3,3 МГц
По умолчанию коэффициент деления равен 6. Это означает, что процессор фактически работает на частоте 3,333 МГц, когда предохранитель OSCCFG запрограммирован на 20 МГц.
Решение
Используйте правильный F_CPU
Если более медленный процессор не является для вас проблемой, вы можете просто сообщить компилятору правильную частоту процессора, изменив #define F_CPU 20000000UL
на #define F_CPU 3333333UL
.
Или отключить частотное разделение
В качестве альтернативы вы можете отключить частотное разделение и запустить процессор на полной частоте 20 МГц.
#define F_CPU 20000000UL
int main(void)
{
/* Set CPU clock to 20 MHz */
_PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0);
/* your code */
}
Но не разгоняйте процессор
Тем не менее, вы должны отметить, что работа на частоте 20 МГц гарантируется Atmel только при напряжении 4,5 В и выше. Если вы используете микроконтроллер при более низком напряжении, например 3,3 В, вы разгоняете процессор, выводя его за пределы безопасной рабочей зоны, обозначенной Atmel. См. Таблицу на странице 473.
Источник: Спецификация микрочипа ATTiny804 / 1604, добросовестное использование.
Хотя разогнанный микроконтроллер, вероятно, будет работать, и в хобби-проекте вы вряд ли увидите какие-либо проблемы. Но все же на данный момент нет гарантии стабильности от производителя. Например, микроконтроллер официально имеет температуру 105 ° C, но разогнанный микроконтроллер может начать давать сбои. Также вероятно повышенное энергопотребление. Наихудшей возможной проблемой может быть таинственная неисправность при определенных редких условиях. Таким образом, если важна надежность и стабильность, не следует разгонять микроконтроллер.
При напряжении 3,3 В, при тактовой частоте системы 20 МГц, процессор должен работать только на частоте 10 МГц, установив значение предварительной настройки в 2 раза. И при напряжении 1,8 В, при частоте 5 МГц с 4-кратным прескалером.
/* Set CPU clock to 10 MHz */
_PROTECTED_WRITE(CLKCTRL_MCLKCTRLB,
CLKCTRL_PDIV_2X_gc | CLKCTRL_PEN_bm);
/* Set CPU clock to 5 MHz */
_PROTECTED_WRITE(CLKCTRL_MCLKCTRLB,
CLKCTRL_PDIV_4X_gc | CLKCTRL_PEN_bm);
- более низкая тактовая частота, чем ожидалось на attiny202
- software serial не работает со скоростью > 4800 бит/с.
- При использовании Arduino Uno в качестве ISP: "Yikes! Invalid device signature" - плохое соединение, неверную конфигурацию или неверную версию avrdude?
- Связь ATtiny85 с компьютером через USB
- Получить доступ к EEPROM ATtiny с помощью кода Arduino?
- avrdude: ошибка проверки, первое несоответствие в байте 0x0000 : 0x00 != 0x16 с использованием USBasp
- Постоянный выход тактовой частоты Arduino
- Радиочастотное дистанционное управление с использованием VirtualWire на ATtiny85, работающем на частоте 8 МГц на внутреннем генераторе