Добрый день. Решил помигать светодиодиком на STM8. В Platformio установил соответствующий пакет, и выбрал пример native-blink (пока пробую без библиотек). В коде примера смотрю на настройку пина, и вижу следующее (привожу лишь необходимые на мой взгляд куски:
То есть, для настройки пина на выход пуш-пулл с быстрыми фронтами, надо выставить соответвующий бит (5 по счету) в 3-х регистрах. И это делается этой хитрой конструкцией. Почему она для меня хитрая ? Потому что в AVR и PIC я привык выставлять биты конструкцией вида DDRB |= 1<<5; Ну и сбрасывать соответственно похожим образом: DDRB &= ~(1<<5); Залез в хидер, нашёл там union, внутри которого структура с битовыми полями. Спойлер
Код:
/** Port A data direction register (DDR at 0x5002) */ union {
/// bytewise access to DDR uint8_t byte;
/// bitwise access to register DDR struct { BITFIELD_UINT DDR0 : 1; // bit 0 BITFIELD_UINT DDR1 : 1; // bit 1 BITFIELD_UINT DDR2 : 1; // bit 2 BITFIELD_UINT DDR3 : 1; // bit 3 BITFIELD_UINT DDR4 : 1; // bit 4 BITFIELD_UINT DDR5 : 1; // bit 5 BITFIELD_UINT DDR6 : 1; // bit 6 BITFIELD_UINT DDR7 : 1; // bit 7 }; // DDR bitfield
/// register _PORT_DDR reset value #define sfr_PORT_DDR_RESET_VALUE ((uint8_t) 0x00)
} DDR;
но как сбрасывать, так и не понял. Как с помощью этой конструкции сбросить бит в регистре ?
LED_PORT.DDR.byte - это обращение ко всем битам, то есть к /// bytewise access to DDR uint8_t byte; И можете работать с ним как раньше.
Union объединяет эти определения или делает эквивалентным их или проецирует этот байт на структуру и обратно (не знаю, как лучше сказать...) то есть, к биту можно обратиться как LED_PORT.DDR.DDR0 = 0
Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.
...к биту можно обратиться как LED_PORT.DDR.DDR0 = 0
Вот, такое обращение с использованием битовых полей для меня логично и понятно)) Ранее с обьединениями дела не имел, лишь вскользь читал в Кернигане и Ричи. То есть, для сброса бита при обращении к структуре объединения как к целому байту мне необходимо писать LED_PORT.DDR.byte &= ~(LED_PIN); ? И правильно ли я понял, что установку битов лучше производить конструкцией типа LED_PORT.DDR.byte |= LED_PIN, иначе если делать как в примере, то все остальные биты регистра будут сбрасываться ?
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
То есть, для сброса бита при обращении к структуре объединения как к целому байту мне необходимо писать LED_PORT.DDR.byte &= ~(LED_PIN); ?
да, но только со сдвигом единички, то есть, (1 << LED_PIN)
Цитата:
установку битов лучше производить конструкцией типа LED_PORT.DDR.byte |= LED_PIN
не знаю, как лучше с точки зрения языка. Конструкция в любом случае будет красивше, так как займёт одну строку, вместо восьми. Однако, возможно, есть алгоритм, где краисвше обратиться в цикле к каждому биту. Ещё может быть разница с точки зрения компилятора.
Цитата:
то все остальные биты регистра будут сбрасываться?
обращаясь к .byte Вы обращаетесь ко всем битам,, соответсвенно. либо сбросятся, либо установятся. Обращаясь к .DDR0 - обращаетесь только к этому биту, никакие другие не будут затронуты,
Вообще, это очень удобно. Например, можете сделать такую структуру:
Код:
/** Port A data direction register (DDR at 0x5002) */ union {
.....
/// bitwise access to register DDR struct { BITFIELD_UINT DDR03 : 4; // bit 0...bit 3 BITFIELD_UINT DDR47 : 4; // bit 4...bit 7 }; // DDR bitfield
/// register _PORT_DDR reset value #define sfr_PORT_DDR_RESET_VALUE ((uint8_t) 0x00)
} DDR;
и в итоге получить обращение к младшему и старшему 4-битным словам. И если вся логика построена на таких словах, это будет удобно.
Зарегистрирован: Вс мар 27, 2022 15:49:30 Сообщений: 16
Рейтинг сообщения:0
Да, тут всё правильно ответили - через CR1 и CR2 задаются режимы работ, в ODR пишется собственно байт на выход порта. Но не стОит останавливаться на этом, есть ещё и альтернативные функции... лучше не программно дёргать, а к таймеру подключить. У меня, например, в управляшке для бесколлекторного мотора TIM2 работает генератором сигнала (TIM2_OC2Init(TIM2_OCMODE_TOGGLE, TIM2_OUTPUTSTATE_ENABLE,CCR2_Val, TIM2_OCPOLARITY_HIGH); - переключает выход с программируемой частотой), а первый таймер - частотомер - захватывает фронты с датчика и измеряет скорость вращения.
Здравствуйте! Подскажите как в STM8S103 заставить работать АЦП2. В нете везде примеры только с АЦП1. Мне же нужно реализовать два независимых канала измерения. Однин на АЦП1 как "Сторож" напряжения. Второй на АЦП2 измерение температуры. Перерыл кучу инфы, так и не получилось заставить измерять по АЦП2. Брал за основу исходник с АЦП1 - измерения происходят нормально. Перенастраиваю исходник на АЦП2 - и не работает. Компилятор SDCC.
/* Right-align data */ //ADC1_CR2 |= (1 << ADC1_CR2_ALIGN); // включить выравнивание по правому краю ADC2_CR2 |= (1 << ADC2_CR2_ALIGN); // включить выравнивание по правому краю
//ADC2_CSR |= (1 << ADC2_CSR_EOCIE); // включить формирование прерываний
/* Wake ADC from power down */
// ADC1_CR1 |= (1 << ADC1_CR1_ADON); //включить питание на АЦП1, второй повтор начнет преобразование ADC2_CR1 |= (1 << ADC2_CR1_ADON); //включить питание на АЦП2, второй повтор начнет преобразование
Ну надо как-то в него добавить второй АЦП, так как их там один.
Вот же шшшшш..... Два дня убил на эту хрень. Перерыл кучу инфы. В учебниказ по STM8 написано что два АЦП. А в даташит именно на этот контроллер посмотреть не додумался. Благодарю за прозрение.
Зарегистрирован: Ср янв 06, 2010 22:02:25 Сообщений: 210 Откуда: Уфа сити
Рейтинг сообщения:0
Добрый день! Пытаюсь обуздать STM8. Задача - сымитировать работу сдвигового регистра. На всякий случай поясню суть: после сигнала latch идет серия тактовых сигналов, по которым отдаем в DATA биты по очереди. Проблема в том, что что latch читается легко, а вот с чтением CLK возникли проблемы. Не пойму, что не так, но либо читается один импульс, либо не читается вообще. СТМка работает на частоте 16мгц.
void proc(void){ while(GPIO_ReadInputPin(LATCH_PORT,LATCH_PIN)==0){}; // Ждем изменения latch for (u8 i = 0; i < 8; i++) { if (data & (1 << i)) dataL(); // сброс бита else dataH(); // установка бита
while( GPIO_ReadInputPin(CLK_PORT, CLK_PIN)==0){}; // Ждем изменения clk }
dataH(); }
В строке while( GPIO_ReadInputPin(CLK_PORT, CLK_PIN)==0) ожидание что 0, что 1 дает один и тот же результат - биты отдаются сразу пачкой, такое ощущение, что чтение порта не работает, хотя сконфигурирован как вход GPIO_Init(CLK_PORT, (GPIO_Pin_TypeDef)(CLK_PIN), GPIO_MODE_IN_FL_NO_IT);
Подобный код на ардуине работал превосходно, даже с учетом тормозов фреймворка Arduino, а тут, на голой СТМке как будто камня не хватает для выборки сигнала..
_________________ Что в цивилизованном мире называют "устаревшие технологии", в России зовется "технологии, проверенные временем"
Последний раз редактировалось Ромыч Вт окт 25, 2022 16:14:42, всего редактировалось 1 раз.
Зарегистрирован: Вс мар 27, 2022 15:49:30 Сообщений: 16
Рейтинг сообщения:0
1. Это в какой среде написано? 2. А для чего - просто для развлекательно-познавательных целей? Вообще-то SPI можно соответственно задаче сконфигурировать. Ну или хотя бы CLK сконфигурировать с прерыванием от изменения уровня - тогда будет точно по переходу 1->0 или 0->1 срабатывать... Здесь же фактически ждётся не изменение CLK, а только пока он равен нулю.
Ромыч, код - адова жесть! Можно ведь использовать таймер или на худой конец прерывания. Не приведено, что внутри функций GPIO_ReadInputPin, dataL, dataH и data1H - об этом нужно догататься самостоятельно? Первая функция сильно похожа на SPL, неужто на несчастную STM8 еще и это дерьмище вкорячили? Жуть!
В общем, прочитав этот код я совершенно не могу даже логику работы понять!
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Зарегистрирован: Ср янв 06, 2010 22:02:25 Сообщений: 210 Откуда: Уфа сити
Рейтинг сообщения:0
Написано в IAR + SPL. Цели - познавательно-развлекательные. SPI, к сожалению, уже занят... CLK вешал на прерывание, но оно тригеррится слишком поздно, когда вся пачка сигналов уже прошла. Как я понял, перед прерыванием выполняются текущие инструкции и (скорее всего) МК работает со стеком для подготовки прерывания. Соответственно, код из обработчика выполняется слишком поздно...
Цитата:
Здесь же фактически ждётся не изменение CLK, а только пока он равен нулю.
не совсем. первый бит выставляется сразу после Latch, далее он должен поменяться после CLK, потому, чисто в целях отладки, без разницы нуля ждать или единицы, максимум, возможен пропуск одного цикла Clk. Проблема в том, что while не работает... не могу понять почему.
Цитата:
Первая функция сильно похожа на SPL, неужто на несчастную STM8 еще и это дерьмище вкорячили? Жуть!
SPL и есть.. а где лучше писать? в STM я совсем новичок, и в местных сортах пенного не разбираюсь. пробовал родную IDE, но что то с космиком не сдружился.. может посоветуете что лучше? ясное дело, что ASM рулит, но пока не готов в него лезть. через ардуиновскую библу тоже нет желания работать.
Зарегистрирован: Вс мар 27, 2022 15:49:30 Сообщений: 16
Рейтинг сообщения:0
И ещё вопрос - какой конкретно контроллер? Если 103f3p6, то у него по умолчанию тактовая /8, т.е. 2 MHz. Чтобы было 16: CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
И ещё вопрос - какой конкретно контроллер? Если 103f3p6, то у него по умолчанию тактовая /8, т.е. 2 MHz. Чтобы было 16: CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
да, именно его, на отладочной чинской платке. CLK_PRESCALER_HSIDIV1 стоит, потому и уточнил, что камень работает на 16мгц
_________________ Что в цивилизованном мире называют "устаревшие технологии", в России зовется "технологии, проверенные временем"
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 7
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения