stm8s103f3p6 с нуля

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

Прошу помощи, инструкции с stm8s103f3p6

Поставил IAR для STM8, st link, st visual programmer. делал по разным инструкциям, но залить так ничего и не получилось

собственно код, все компилируется. синтаксис конечно через жопу, но это вроде можно поправить всякими инклудами

#include "iostm8s103f3.h"

static void delay(unsigned int t)
{
  while(t--);
}



int main( void )
{
  PB_DDR_bit.DDR5 = 1;
  
  while(1){
    delay(1000);
    PB_ODR ^= MASK_PB_ODR_ODR5;
  }
}

взят из инструкции, но напрямую из iar не программируется. получается нужно компилировать, а программировать нужно через st visual programmer? то есть кнопка зеленая со стрелочкой "Downloa and Debug"нам не подходит?

кстати хваленая st link utility для stm8 не подходит, нет в ней выбора swim, только swd

помогите, желательно с картинками. по тексту может показаться я зол, так и есть, пол дня безсполезно потратил практически без результата. лучше уж на ардуине сидеть или использовать STM32F103C8T6

stm8s103f3p6 собирался использовать в одном проекте, просто ногодрыг, ничего серьезного

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Не понял - чего не программируется? В настройках проекта есть, чего использовать - эмулятор или закачивать в плату, может, в этом дело? Или я не понял вопроса?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

в найстройках стоит. прикладываю ошибку

Sun Jul 24, 2016 13:18:11: C-SPY Processor Descriptor V2.20.1.176 for STM8 
Sun Jul 24, 2016 13:18:11: C-SPY Debugger Driver, ST-LINK V2.20.1.176 for STM8 
Sun Jul 24, 2016 13:18:11: Errors while setting configuration with MCU name STM8S103F3P: gdi-error [40301]: The Flash Memory Read-out protection option must be disabled for  
debug. Disabling this option will first erase the whole Flash Memory. 

ну тут я может затупил, блокировка записи. но с другой стороны нафига еще нужен программатор в первую очередь как не для записи)))

как фьюзы в stm называются?))

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

а все просто. методом тыка. в st visual programmer заходим в 3 вкладку снизу option byte. пишет защита отключена, выбираем ее еще раз и заливаем. после этого заливается без проблемм.

ладно тему я оставлю, что получится, шим или ацп буду выкладывать, чего бедных ардуинщиков мучать

кстати кажется a5021 обещал дать настройку, чтобы не писать вырвиглазный код, люблю ардуину))

a5021
Offline
Зарегистрирован: 07.07.2013

Ситуацию, когда из STVP шьется, а из ИАР-а нет, я тоже наблюдал. У меня такое выходило, если МК питался от отдельного источника. Какие уж там чудеса происходят внутри IAR-а сказать сложно, но при запитке МК от самого ST-Linka все начинало работать. Виноват, похоже, IAR, т.к. STVP шьет, что так, что так и не очень похоже, что тут есть какая-то серьезная аппаратная проблема.

Попробуйте эту галку включить на случай, если почему-то IAR не говорит st-link-у, что за чип надо шить.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Тема интересная, продолжаем. Самому на днях пришла STM8L-Discovery, надо как-то щупать начинать. Пока в IAR поигрался только блинком на эмуляторе, плату страшно трогать, боюсь поломати :)

ssss
Offline
Зарегистрирован: 01.07.2016

jeka_tm пишет:

а все просто. методом тыка. в st visual programmer заходим в 3 вкладку снизу option byte. пишет защита отключена, выбираем ее еще раз и заливаем. после этого заливается без проблемм.

ладно тему я оставлю, что получится, шим или ацп буду выкладывать, чего бедных ардуинщиков мучать

кстати кажется a5021 обещал дать настройку, чтобы не писать вырвиглазный код, люблю ардуину))

Можно было сделать и в ИАР в закладке СТ-Линк---Оптионс.

Если уже привыкли к ардуине, то это камень не для вас. ИАРовскими хедерами лучше не пользоваться, лучше родные от СТМ. Но они не полные, не все биты расписаны. Придётся расписать биты по аналогии с СТМ32 самому.

Можно юзать СПЛ от СТМ, но тогда весь потенциал камня не раскрывается.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

под родными от stm имеется в виду эта? если да как ее установить?

ssss
Offline
Зарегистрирован: 01.07.2016

А чего вы так нервно? Я поделился инфой, и только. Никаких "свысока" и не было. Я к тому, что ардуиновский подход здесь не прокатит. Это больше камень для профи, которым пофигу что и на чём писать. Если пороетесь по темам СТМ8, то увидите какой там бардак. Поэтому особо внятной инфы можете и не найти, каждый всё пишет по своему. Поэтому, если решили его осваивать, то привыкайте к мысли что практически всё придётся делать самому. Это и всё что я хотел сказать.

СТМ8 хороши для простых задач на нижнем уровне, без надстроек типа СПЛ и прочего. Весь цимус у них это железо, т.к. ЦП у них всё таки слабенькое, аккумуляторное. Набор команд как-то это нивелирует, но всё равно. Если у вас уж совсем простые задачи, то тогда конечно всё равно что и как.

Мягко говоря, СТМ8 в выигрыше там, где на других МК задачу не решить, ввиду отсутствия соответствующего железа, или это выливается в гемор. Из больших плюсов - периферия похожа на СТМ32.

ssss
Offline
Зарегистрирован: 01.07.2016

jeka_tm пишет:

под родными от stm имеется в виду эта?

Я говорил про хедер камня. Вы юзаете ИАРовский, я предложил юзать stm8s.h, тогда проще прыгать с СТМ32 на СТМ8 и обратно. Но это в общем на любителя.

А это СПЛ для СТМ8.

http://www.st.com/content/st_com/en/products/embedded-software/mcus-embe...

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

ну ничего пока желание не пропало. если есть что конкретно предложить например ногодрыг с более удобными функциями буду только рад

a5021
Offline
Зарегистрирован: 07.07.2013

В SPL действительно не имеет особого залезать, но вот насчет хедеров я бы поспорил. В плане изучения и наглядности, иаровские заголовочные файлы предпочтительней. Каждый бит можно дергать простым выражением. На СТМ-овских хедерах код получается более компактный, что плюс, но менее наглядный и само-документируемый, что, безусловно, минус.

Еще могу посоветовать покопаться в примерах Марка Стивенса. Он подробно описывает, что и как делает и код хорошо комментирован.

Какую я настройку общал дать, я не понял. Если объясните и я действтиельно это общал, то наверное дам.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

хедер и имел в виду. можно для примера  записи 1 и 0 в регистр на iar и stm хедерах. сравнить чтло удобнее и понятнее

но утверждать не буду, ты как то завел тему про эти стм, вот и показалось ты обещал, но может axill

a5021
Offline
Зарегистрирован: 07.07.2013

Ну вот оно дрыгание ногой. Пятый пин порта "B" формирует положительный импульс некой ширины:

// запись для иаровских хедеров
PB_ODR_ODR5 = 1;
_delay_ms(x);
PB_ODR_ODR5 = 0;

// запись для стмовских хедеров
GPIOB->ODR |= (1 << 5);
_delay_ms(x);
GPIOB->ODR &= ~(1 << 5);

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

да уж)) iar удобнее. понятнее чтоли

вот что понял после гугления

//настройка на выход

PB_DDR_DDR5=1;    //настроить на выход B5
PB_CR1_C15 =1;    //если 1 то Push-Pull
                  //если 0 то Open drain
PB_CR2_C25 =1;    //если 1 то до 10МГц
                  //если 0 то до  2МГц
//управление пином
PB_ODR_ODR5=1;    //если 1 то HIGH на выходе
                  //если 0 то LOW  на выходе

только непонятно какое будет состояние выходов если только настроить на выход, не указывая тип выхода и частоту, короче какой выход по умолчанию?

//настройка на вход
PB_DDR_DDR5=0;    // настроить на вход
PB_CR1_C15 =1;    //если 1 то вход с подтягивающим резистором
                  //если 0 то плавающий вход
PB_CR2_C25 =1;    //если 1 то прерывания разрешены
                  //если 0 то прерывания запрещены
//считать со входа
t=PB_IDR_IDR5;

только не понял куда подтянут вход к земле или плюсу, наверно к плюсу

и правильно ли я написал как считывать состояние пина?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

a5021 пишет:

Ну вот оно дрыгание ногой. Пятый пин порта "B" формирует положительный импульс некой ширины:

// запись для иаровских хедеров
PB_ODR_ODR5 = 1;
_delay_ms(x);
PB_ODR_ODR5 = 0;

// запись для стмовских хедеров
GPIOB->ODR |= (1 << 5);
_delay_ms(x);
GPIOB->ODR &= ~(1 << 5);

 

Запись для CTMовских хидеров мне кажется более понятной и удобной.

a5021
Offline
Зарегистрирован: 07.07.2013

Open Drain -- тип выхода по умолчанию. Если его не менять, то для формирования импульсов на выходе, этот выход надо подтягивать резистором к плюсу. Образно говоря, в полумосте выходного формирователя отсутствует верхний мосфет. К земле пин прижать можно, а вот поднять над землей только за счет влияния извне.

Частота там, это даже не частота, а скорость нарастания выходного сигнала. Ее сделали регулируемой, чтобы снизить потребление выходного формирователя. По умолчанию потребление низкое, фронты пологие (относительно, 2мгц, как никак). Хочется фронты поострее, нужно включать 10мгц.

DIYMan пишет:
Запись для CTMовских хидеров мне кажется более понятной и удобной.

Привычка, не более. Понятийно иаровкие хедеры удобнее. Пишем единицу --- взводим пин, ноль -- опускаем. А на стмовских хедерах куча крчков и палочек. Опытный глаз безусловно различает, что к чему, но на этот навык нужна тренировка.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

а со входом у меня правильно написано?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

делаю ардуину))

#include "jeka_stm8s.h"

int main( void )
{
  D4_OUTPUT;
  D5_OUTPUT;
  
  while(1){
    delay(100);
    D4_HIGH;
    D5_LOW;
    delay(100);
    D4_LOW;
    D5_HIGH;
  }
}

главное работает)) к чему все эти длинные названия запоминать)) кстати по эта настройка D5_OUT настраивает на выход пуш-пул 2мгц. по момему самый оптимальный по умолчанию. надо другой режим - придется писать полные настройки или дополнить хедер. сейчас выглядит так:

delay не стал показывать, делает задержку с еденицей измерения попугай, поэтому не стоит))

#include "iostm8s103f3.h"

// Порт A
#define A1_OUTPUT PA_DDR_DDR1=1; PA_CR1_C11=1
#define A2_OUTPUT PA_DDR_DDR2=1; PA_CR1_C12=1
#define A3_OUTPUT PA_DDR_DDR3=1; PA_CR1_C13=1

#define A1_HIGH PA_ODR_ODR1=1
#define A2_HIGH PA_ODR_ODR2=1
#define A3_HIGH PA_ODR_ODR3=1

#define A1_LOW  PA_ODR_ODR1=0
#define A2_LOW  PA_ODR_ODR2=0
#define A3_LOW  PA_ODR_ODR3=0

// Порт B
#define B4_OUTPUT PB_DDR_DDR4=1; PB_CR1_C14=1
#define B5_OUTPUT PB_DDR_DDR5=1; PB_CR1_C15=1

#define B4_HIGH PB_ODR_ODR4=1
#define B5_HIGH PB_ODR_ODR5=1

#define B4_LOW  PB_ODR_ODR4=0
#define B5_LOW  PB_ODR_ODR5=0

// Порт C
#define C3_OUTPUT PC_DDR_DDR3=1; PC_CR1_C13=1
#define C4_OUTPUT PC_DDR_DDR4=1; PC_CR1_C14=1
#define C5_OUTPUT PC_DDR_DDR5=1; PC_CR1_C15=1
#define C6_OUTPUT PC_DDR_DDR6=1; PC_CR1_C16=1
#define C7_OUTPUT PC_DDR_DDR7=1; PC_CR1_C17=1

#define C3_HIGH PC_ODR_ODR3=1
#define C4_HIGH PC_ODR_ODR4=1
#define C5_HIGH PC_ODR_ODR5=1
#define C6_HIGH PC_ODR_ODR6=1
#define C7_HIGH PC_ODR_ODR7=1

#define C3_LOW  PC_ODR_ODR3=0
#define C4_LOW  PC_ODR_ODR4=0
#define C5_LOW  PC_ODR_ODR5=0
#define C6_LOW  PC_ODR_ODR6=0
#define C7_LOW  PC_ODR_ODR7=0

// Порт D
#define D1_OUTPUT PD_DDR_DDR1=1; PD_CR1_C11=1
#define D2_OUTPUT PD_DDR_DDR2=1; PD_CR1_C12=1
#define D3_OUTPUT PD_DDR_DDR3=1; PD_CR1_C13=1
#define D4_OUTPUT PD_DDR_DDR4=1; PD_CR1_C14=1
#define D5_OUTPUT PD_DDR_DDR5=1; PD_CR1_C15=1
#define D6_OUTPUT PD_DDR_DDR6=1; PD_CR1_C16=1

#define D1_HIGH PD_ODR_ODR1=1
#define D2_HIGH PD_ODR_ODR2=1
#define D3_HIGH PD_ODR_ODR3=1
#define D4_HIGH PD_ODR_ODR4=1
#define D5_HIGH PD_ODR_ODR5=1
#define D6_HIGH PD_ODR_ODR6=1

#define D1_LOW  PD_ODR_ODR1=0
#define D2_LOW  PD_ODR_ODR2=0
#define D3_LOW  PD_ODR_ODR3=0
#define D4_LOW  PD_ODR_ODR4=0
#define D5_LOW  PD_ODR_ODR5=0
#define D6_LOW  PD_ODR_ODR6=0

a5021
Offline
Зарегистрирован: 07.07.2013

Вход правильно, а подтяжка включается и выключается в Px_CR1. Px_CR2 для подключения внешних прерываний.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

подтяжка к Vcc?

короче все пины проверил, на всех есть меандр кроме D1 и B4

на D1 постоянно 1 и с муосором периодическим на землю. на B4 земля с небольшими наводками. есть мысли?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

в iar можно узнать сколько памяти занято? и флеш и оперативка

ssss
Offline
Зарегистрирован: 01.07.2016

jeka_tm пишет:

короче все пины проверил, на всех есть меандр кроме D1 и B4

на D1 постоянно 1 и с муосором периодическим на землю. на B4 земля с небольшими наводками. есть мысли?

D1 - SWIM

B4 и B5 - (T) True open drain (P-buffer and protection diode to VDD not implemented).

ssss
Offline
Зарегистрирован: 01.07.2016

DIYMan пишет:

Запись для CTMовских хидеров мне кажется более понятной и удобной.

Это классика. Будет работать и на других МК.

 

ssss
Offline
Зарегистрирован: 01.07.2016

a5021 пишет:

Понятийно иаровкие хедеры удобнее. Пишем единицу --- взводим пин, ноль -- опускаем. А на стмовских хедерах куча крчков и палочек. Опытный глаз безусловно различает, что к чему, но на этот навык нужна тренировка.

Как будет выглядеть групповая установка-сброс битов с ИАРовскими хедерами?

ssss
Offline
Зарегистрирован: 01.07.2016

jeka_tm пишет:

делаю ардуину))

А зачем? Почему не писать осмысленно LED_RED_ON или MOTOR_ON, вместо бессмысленного D4_HIGH?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

немного поправил на всякий случай, вруг "частота" пина менялась

#include "iostm8s103f3.h"

// Порт A
#define A1_OUTPUT PA_DDR_DDR1=1; PA_CR1_C11=1; PA_CR2_C21 =0
#define A2_OUTPUT PA_DDR_DDR2=1; PA_CR1_C12=1; PA_CR2_C22 =0
#define A3_OUTPUT PA_DDR_DDR3=1; PA_CR1_C13=1; PA_CR2_C23 =0

#define A1_HIGH PA_ODR_ODR1=1
#define A2_HIGH PA_ODR_ODR2=1
#define A3_HIGH PA_ODR_ODR3=1

#define A1_LOW  PA_ODR_ODR1=0
#define A2_LOW  PA_ODR_ODR2=0
#define A3_LOW  PA_ODR_ODR3=0

// Порт B
#define B4_OUTPUT PB_DDR_DDR4=1; PB_CR1_C14=1; PB_CR2_C24 =0
#define B5_OUTPUT PB_DDR_DDR5=1; PB_CR1_C15=1; PB_CR2_C25 =0

#define B4_HIGH PB_ODR_ODR4=1
#define B5_HIGH PB_ODR_ODR5=1

#define B4_LOW  PB_ODR_ODR4=0
#define B5_LOW  PB_ODR_ODR5=0

// Порт C
#define C3_OUTPUT PC_DDR_DDR3=1; PC_CR1_C13=1; PC_CR2_C23 =0
#define C4_OUTPUT PC_DDR_DDR4=1; PC_CR1_C14=1; PC_CR2_C24 =0
#define C5_OUTPUT PC_DDR_DDR5=1; PC_CR1_C15=1; PC_CR2_C25 =0
#define C6_OUTPUT PC_DDR_DDR6=1; PC_CR1_C16=1; PC_CR2_C26 =0
#define C7_OUTPUT PC_DDR_DDR7=1; PC_CR1_C17=1; PC_CR2_C27 =0

#define C3_HIGH PC_ODR_ODR3=1
#define C4_HIGH PC_ODR_ODR4=1
#define C5_HIGH PC_ODR_ODR5=1
#define C6_HIGH PC_ODR_ODR6=1
#define C7_HIGH PC_ODR_ODR7=1

#define C3_LOW  PC_ODR_ODR3=0
#define C4_LOW  PC_ODR_ODR4=0
#define C5_LOW  PC_ODR_ODR5=0
#define C6_LOW  PC_ODR_ODR6=0
#define C7_LOW  PC_ODR_ODR7=0

// Порт D
#define D1_OUTPUT PD_DDR_DDR1=1; PD_CR1_C11=1; PD_CR2_C21 =0
#define D2_OUTPUT PD_DDR_DDR2=1; PD_CR1_C12=1; PD_CR2_C22 =0
#define D3_OUTPUT PD_DDR_DDR3=1; PD_CR1_C13=1; PD_CR2_C23 =0
#define D4_OUTPUT PD_DDR_DDR4=1; PD_CR1_C14=1; PD_CR2_C24 =0
#define D5_OUTPUT PD_DDR_DDR5=1; PD_CR1_C15=1; PD_CR2_C25 =0
#define D6_OUTPUT PD_DDR_DDR6=1; PD_CR1_C16=1; PD_CR2_C26 =0

#define D1_HIGH PD_ODR_ODR1=1
#define D2_HIGH PD_ODR_ODR2=1
#define D3_HIGH PD_ODR_ODR3=1
#define D4_HIGH PD_ODR_ODR4=1
#define D5_HIGH PD_ODR_ODR5=1
#define D6_HIGH PD_ODR_ODR6=1

#define D1_LOW  PD_ODR_ODR1=0
#define D2_LOW  PD_ODR_ODR2=0
#define D3_LOW  PD_ODR_ODR3=0
#define D4_LOW  PD_ODR_ODR4=0
#define D5_LOW  PD_ODR_ODR5=0
#define D6_LOW  PD_ODR_ODR6=0

блин они еще и пин программирования развели. имеет смысл для готового устройства, например пинов не хватает, а менять прошивку не будут. глупо, ну ладно

B4 и B5 значит имеет только open drain. ну ладно. спасибо

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

ssss пишет:

А зачем? Почему не писать осмысленно LED_RED_ON или MOTOR_ON, вместо бессмысленного D4_HIGH?

что писать в дефайне для MOTOR_ON? если не помнишь значит октрываешь инк и вспоминаешь, либо 

#define MOTOR_ON D4_HIGH

ну это мой подход. по максимому упростить, оформить в функции чтобы не тратить время на поиск инфы, а это я запомню. я никого не принуждаю, мне так удобно. я не программист все таки, каждый день не программирую

ssss
Offline
Зарегистрирован: 01.07.2016

jeka_tm пишет:

в iar можно узнать сколько памяти занято? и флеш и оперативка

В закладке Tools --> Options -->Messages в поле Show build messages выбрать All.

ssss
Offline
Зарегистрирован: 01.07.2016

jeka_tm пишет:

мне так удобно. я не программист все таки, каждый день не программирую

Понимаю, но D4_HIGH не несёт никакой информации. Через некоторое время можно просто забыть что это такое и для чего.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

спасибо. согласен, но к хедеру будет простая мини инструкция, а после нее аналог того что в 14 посте. так что можно будет и так и так

кстати по шиму кто может подсказать? чтобы оформить в виде функции. да и опрос ацп хотелось бы

 

a5021
Offline
Зарегистрирован: 07.07.2013

Я обычно вообще макросы оформляю с закосом под функцию. Типа такого:

#define CSN_LOW()       PD_ODR_ODR2 = 0;
#define CSN_HIGH()      PD_ODR_ODR2 = 1;

#define CE_LOW()        PD_ODR_ODR3 = 0;
#define CE_HIGH()       PD_ODR_ODR3 = 1;

ssss пишет:
Как будет выглядеть групповая установка-сброс битов с ИАРовскими хедерами?

А в чем проблема? У ИАРа определены и регистры целиком и биты поотдельности.

PD_ODR = (PD_ODR & ~((1 << 2) | (1 << 4) | (1 << 6))) | ((1 << 1) | (1 << 3) | (1 << 5));

Это наоборот, наглядно по одному битику шевелить на стмовских хедерах не получится, а в стмовском стиле писать на хедерах иара можно сколько влезет.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

можно и с закосом под функцию, можно и вообще функцию сделать как в ардуине, но передавать только значение например для управления выходом, так как маски и тп я не осилю

но лучше как по мне сделать так. мои дефайны остались есть , но в программе добавляем такой дефайн

#define Led(x) D5_HIGH:D5_LOW

вроде так пишется. и ssss должно больше понравится

a5021
Offline
Зарегистрирован: 07.07.2013

jeka_tm пишет:
кстати по шиму кто может подсказать? чтобы оформить в виде функции. да и опрос ацп хотелось бы

Дал же в одиннадцатом посте ссылку. Там все это есть. Разжевано до молекул.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

a5021 пишет:

Дал же в одиннадцатом посте ссылку. Там все это есть. Разжевано до молекул.

ты про это?

//
//  Set up Timer 1, channel 4 to output a PWM signal (the carrier signal).
//
void SetupTimer1()
{
    TIM1_ARRH = *((unsigned char *) EEPROM_PULSE_DURATION);
    TIM1_ARRL = *((unsigned char *) (EEPROM_PULSE_DURATION + 1));
    TIM1_PSCRH = *((unsigned char *) EEPROM_PRESCALAR_OFFSET);
    TIM1_PSCRL = *((unsigned char *) (EEPROM_PRESCALAR_OFFSET + 1));
    //
    //  Now configure Timer 1, channel 4.
    //
    TIM1_CCMR4_OC4M = 7;    //  Set up to use PWM mode 2.
    TIM1_CCER2_CC4E = 1;    //  Output is enabled.
    TIM1_CCER2_CC4P = 0;    //  Active is defined as high.
    //
    //  Work out the 50% duty cycle based upon the count.
    //
    unsigned short fiftyPercentDutyCycle;
    fiftyPercentDutyCycle = *((unsigned char *) EEPROM_PULSE_DURATION);
    fiftyPercentDutyCycle <<= 8;
    fiftyPercentDutyCycle += *((unsigned char *) (EEPROM_PULSE_DURATION + 1));
    fiftyPercentDutyCycle >>= 1;
    TIM1_CCR4H = ((fiftyPercentDutyCycle >> 8) &amp; 0xff);
    TIM1_CCR4L = fiftyPercentDutyCycle &amp; 0xff;
    //
    TIM1_BKR_MOE = 0;       //  Disable the main output.
    TIM1_CR1_CEN = 1;       //  Enable the timer.
}

видно мне нужно до атомов)) я даже не понял на каком пине он настроил шим. по документации всего 3 шима. я правильно понял?

16-bit general purpose timer, with 3 CAPCOM
channels (IC, OC or PWM)

 

ssss
Offline
Зарегистрирован: 01.07.2016

a5021 пишет:

ssss пишет:
Как будет выглядеть групповая установка-сброс битов с ИАРовскими хедерами?

А в чем проблема? У ИАРа определены и регистры целиком и биты поотдельности.

PD_ODR = (PD_ODR & ~((1 << 2) | (1 << 4) | (1 << 6))) | ((1 << 1) | (1 << 3) | (1 << 5));

Это наоборот, наглядно по одному битику шевелить на стмовских хедерах не получится, а в стмовском стиле писать на хедерах иара можно сколько влезет.

Мда. Запись просто внушает страх.

ssss
Offline
Зарегистрирован: 01.07.2016

jeka_tm пишет:

я даже не понял на каком пине он настроил шим. 

Это

    unsigned short fiftyPercentDutyCycle;
    fiftyPercentDutyCycle = *((unsigned char *) EEPROM_PULSE_DURATION);
    fiftyPercentDutyCycle <<= 8;
    fiftyPercentDutyCycle += *((unsigned char *) (EEPROM_PULSE_DURATION + 1));
    fiftyPercentDutyCycle >>= 1;
    TIM1_CCR4H = ((fiftyPercentDutyCycle >> 8) &amp; 0xff);
    TIM1_CCR4L = fiftyPercentDutyCycle &amp; 0xff;

вообще не поддаётся пониманию.

a5021
Offline
Зарегистрирован: 07.07.2013

ssss пишет:
Мда. Запись просто внушает страх.

И я говорю. То ли дело на иаровских:

  PD_ODR_ODR1 = 1;
  PD_ODR_ODR2 = 0;
  PD_ODR_ODR3 = 1;
  PD_ODR_ODR4 = 0;
  PD_ODR_ODR5 = 1;
  PD_ODR_ODR6 = 0;

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

изза особенностей пинов B4 и B5 они могут работать как цифровые входы? если да то как насчет входа с подтяжкой

 

a5021
Offline
Зарегистрирован: 07.07.2013

Оп. Сначала написал одно, а потом посмотрел даташит. Оказалось, с подтяжкой там труба. Извиняюсь за дезу.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

хорошо) спасибо

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

да тоже узнал. проверял все пины с подтяжкой кроме B5, использовал как индикатор. B4 тоже не работает. то есть подтяжки нет, а как вход работать может?

ну чтобы вы не говорили мне нравится)) вот например код для теста

#include "jeka_stm8s.h"

int main( void ){
  A1_INPUT_UP;
  A2_INPUT_UP;
  A3_INPUT_UP;

  B5_OUTPUT;
  
  
  while(1){
    if(!A1_READ ||!A2_READ ||!A3_READ) B5_LOW;
    else B5_HIGH;
  }
}

пожалуй сделаю под функции дефайны, а то как то не смотрится, вдруг с переменной перепутают

ssss
Offline
Зарегистрирован: 01.07.2016

jeka_tm пишет:

B4 тоже не работает. то есть подтяжки нет, а как вход работать может?

Может.

Цитата:

пожалуй сделаю под функции дефайны, а то как то не смотрится, вдруг с переменной перепутают

Делайте как хотите. В инете под СТМ8 ещё и не такое можно встретить.

ssss
Offline
Зарегистрирован: 01.07.2016

a5021 пишет:

ssss пишет:
Мда. Запись просто внушает страх.

И я говорю. То ли дело на иаровских:

  PD_ODR_ODR1 = 1;
  PD_ODR_ODR2 = 0;
  PD_ODR_ODR3 = 1;
  PD_ODR_ODR4 = 0;
  PD_ODR_ODR5 = 1;
  PD_ODR_ODR6 = 0;

 

Вообще ужас и тормоз к тому же!

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

jeka_tm пишет:

пожалуй сделаю под функции дефайны, а то как то не смотрится, вдруг с переменной перепутают

Только чур наработки в шкаф не прятать ;)

a5021
Offline
Зарегистрирован: 07.07.2013

ssss пишет:
Вообще ужас и тормоз к тому же!

Ваш-то вариант секретный наверное?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

ssss пишет:

Делайте как хотите. В инете под СТМ8 ещё и не такое можно встретить.

где? я не от хорошей жизни целый день на это потратил. было бы то что более менее меня устроило бы стал бы я заморачиваться

но все же для сравнения

#include "jeka_stm8s.h"

int main( void ){
  A1_INPUT_UP();
  A2_INPUT_UP();
  A3_INPUT_UP();

  B5_OUTPUT();
  
  
  while(1){
    if(!A1_READ() ||!A2_READ() ||!A3_READ()) B5_LOW();
    else B5_HIGH();
  }
}
#include "iostm8s103f3.h"

int main( void ){
  PA_DDR_DDR1=1; PA_CR1_C11=1; PA_CR2_C21 =0
  PA_DDR_DDR2=1; PA_CR1_C12=1; PA_CR2_C22 =0
  PA_DDR_DDR3=1; PA_CR1_C13=1; PA_CR2_C23 =0

  PB_DDR_DDR5=1; PB_CR1_C15=1; PB_CR2_C25 =0
  
  
  while(1){
    if(!PA_IDR_IDR1 ||!PA_IDR_IDR2 ||!PA_IDR_IDR3) PB_ODR_ODR5=0;
    else PB_ODR_ODR5=1;
  }
}

ничего не прячу. пока умеет только настраивать на вход и выход записывать и считывать. есть также инфа как остальные варианты настроить

a5021
Offline
Зарегистрирован: 07.07.2013

Вот генерация таймером ШИМа с сайта Марка:

//--------------------------------------------------------------------------------
//
//  Set up Timer 1, channel 4 
//
void SetupTimer1()
{
    TIM1_ARRH = 0x00;       //  Reload counter = 51
    TIM1_ARRL = 0x33;
    TIM1_PSCRH = 0;         //  Prescalar = 0 (i.e. 1)
    TIM1_PSCRL = 0;
    //
    //  Now configure Timer 1, channel 4.
    //
    TIM1_CCMR4_OC4M = 7;    //  Set up to use PWM mode 2.
    TIM1_CCER2_CC4E = 1;    //  Output is enabled.
    TIM1_CCER2_CC4P = 0;    //  Active is defined as high.
    TIM1_CCR4H = 0x00;      //  26 = 50% duty cycle (based on TIM1_ARR).
    TIM1_CCR4L = 0x1a;
    TIM1_BKR_MOE = 1;       //  Enable the main output.
}

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

объясни пожалуйста на каком пине генерируется шим, как настроить для двух остальных. какой диапазон значений можно записывать в регистры , и как поменять частоту шим. если пойму проверю и добавлю

вот собственно инструкция. надеюсь все понятно и я ничего не зыбыл

a5021
Offline
Зарегистрирован: 07.07.2013

jeka_tm пишет:
объясни пожалуйста на каком пине генерируется шим,

Там в коментариях написано какой таймер и какой канал. Теперь ищем его на распиновке.

Я конечно и пальцем могу показать, но когда самому приходится искать, то лучше запомнается. :)

Цитата:
как настроить для двух остальных.

Для двух остальных чего? Каналов или таймеров? Если таймеров, то у 8-битного таймера шим-каналов нет, если каналов, то смотри регистры, но обрати внимание, что часть параметров распихана по двум регистрам: TIM1_ССER1 и TIM1_CCER2. Параметры 1-го и 2-го канала задаются в TIM1_ССER1, а 3-го и 4-го в TIM1_CCER2.

Еще момент: в приведенной выше процедуре инициализации таймера для генерации ШИМ, таймер на счет не запущен. То есть, он полностью готов генерировать, но остановлен. Чтобы стартовать его, надо поднять бит TIM1_CR1_CEN

TIM1_CR1_CEN = 1;

Если пофиг, когда стартовать, можно эту строчку воткнуть в вышеприведенную процедуру последней.

Цитата:
какой диапазон значений можно записывать в регистры

От разрядности регистров зависит. В 16-битные регистры любое число до 65535, в восьмибитные до 255.

Цитата:
и как поменять частоту шим

Частота, с которой считает таймер, зависит от значения прескалера. Это 16-битный регистр, состоящий из двух 8-битных TIM1_PSCRL и TIM1_PSCRH. По умолчанию он равен нулю и это означает, что таймер считает с частотой тактирования ядра, т.е. обычно 16мгц. Если записать туда единицу, таймер будет считать на 8мгц, двойку на 16мгц/3, тройку 4мгц и т.д.

Оставим пока прескалер, пусть он остается в нуле и таймер тем самым считает с частотой ядра.

Таймер считает, пока его счетчик не сравняется со значением записанным в TIM1_ARR (это пара регистров TIM1_ARRL и TIM1_ARRH). Когда сравняется, счетчик сбрасывается и считает заново. Если было разрешено прерывание по переполнению, оно вызывается в момент сброса.

Если нам надо входную частоту поделить, скажем на 16, чтобы на выходе получился 1мгц, в ARR надо записать 16-1, т.е. 15. А удобнее так и писать:

TIM1_ARRH = 0;
TIM1_ARRL = 16 - 1;

Если нужен 1кгц на выходе таймера, то в ARR надо писать 16000 -1 (0x3E7F)

TIM1_ARRH = 0x3E;
TIM1_ARRL = 0x7F;

Коэффициент заполнения ШИМ-сигнала задается в 16-битном регистре TIM1_CCR4 (4 канал). Можно сразу пересчитывать в проценты каким-то таким образом

// пусть коэффициент заполнения будет 25% для примера
#define DUTY_CYCLE        25
uint16_t ccr = (uint16_t) (TIM1_ARRH << 8) | TIM1_ARRL; // склеиваем 16 бит из двух половин
ccr += 1; // возвращаем единицу чтобы  не потерять точность счета
ccr = (uint32_t)(ccr * DUTY_CYCLE) / 100; // находим значение для заданных процентов
ccr -= 1; // опять отнимаем единицу
TIM1_CCR4H = ccr >> 8; //задаем старшие 8 бит
TIM1_CCR4L = ccr; // младшие

Я не проверял этот код, т.ч. мог где и ляпнуть, но общий смысл должен быть такой.

a5021
Offline
Зарегистрирован: 07.07.2013

Посмотрел я сегодня на эту ветку и как-то меня прибило: нафига я все время при распределении ног всякие портянки пишу из повторяющихся почти одинаковых строк. И подумал я, что надо как-то подсократить эту запись и к ардуиновскому стилю приблизить. Посмотрел, как делают другие, но ничего не глянулось. Все равно получается длинно и не очень читаемо. Взялся писать свое. Что получилось, смотрим:

//
//  definitions to configure a pin in input mode
//

#define INPUT                   0
#define FLOAT                   0
#define PULL_UP                 (1 << 1)
#define NO_INT                  0
#define INT                     (1 << 0)

  // most common pin settings for input mode
#define INPUT_MODE              PULL_UP

//
//  definitions to configure a pin in output mode
//

#define OUTPUT                  (1 << 2)
#define OPEN_DRAIN              0
#define PUSH_PULL               (1 << 1)
#define LOW_SPEED               0
#define HIGH_SPEED              (1 << 0)

  // most common pin settings for output mode
#define OUTPUT_MODE             OUTPUT + PUSH_PULL + HIGH_SPEED

//
//   pin state
//
  
#define LOW     0
#define HIGH    1

  // macro to configure a pin
#define PIN_MODE(PORT, PIN, MODE)\
          P##PORT##_DDR_DDR##PIN = (MODE) >> 2;\
          P##PORT##_CR1_C1##PIN = ((MODE) >> 1) & 1;\
          P##PORT##_CR2_C2##PIN = (MODE) & 1

  // macro to set a pin
#define PIN_WRITE(PORT, PIN, VALUE)\
          P##PORT##_ODR_ODR##PIN = VALUE
                                      
  // macro to get state of a pin
#define PIN_READ(PORT, PIN)\
          P##PORT##_IDR_IDR##PIN

Макросы по виду получились слегка зубодробительные, но работают так, как требуется. Положим, надо сконфигурировать четвертый пин порта С на вход без подтяжки. В этом случае макрос PIN_MODE вызывается в таком виде:

PIN_MODE(C, 4, INPUT + FLOAT + NO_INT);

где С -- это имя порта, 4 -- номер пина этого порта, INPUT -- режим входа, FLOAT -- без подтяжки, NO_INT -- прервание не использовать. Если нужно включить подтяжку, то запись станет выглядеть так:

PIN_MODE(C, 4, INPUT + PULL_UP + NO_INT);

а надо включить прерывание на этом пине, то вот так:

PIN_MODE(C, 4, INPUT + PULL_UP + INT);

Если посмотреть в определения, то часть их соответствуют нулю и операция сложения вообщем-то выглядит бессмысленной. Это действительно так, но "пустые" сложения можно просто использовать для самодокументированности кода. Тот же первый пример можно записать, как

PIN_MODE(C, 4, INPUT);

Обе записи совершенно эквивалентны, т.е. пин на вход, без подтяжки и прерывания, но первая более подробна и понятна для прочтения.

Что же касательно режимов пина на выход, то они тоже могут быть установлены в различных вариантах этим же макросом. Например, запись вида

PIN_WRITE(D, 3, LOW);
PIN_MODE(D, 3, OUTPUT + PUSH_PULL + HIGH_SPEED);

сначала готовит состояние пина 3 порта D (ноль в данном случае), в котором он окажется, когда будет включен на вывод. А в следующей строке выполняется переключение для работы на выход в режиме PUSH-PULL и с установками выходного формирователя для работы на высокой скорости.

Так как данные установки довольно часто используются при работе пина на выход, то в оперделениях они описаны отдельным дифайном OUTPUT_MODE. Таким образом, вышеприведенный код будет полностью эквивалентен коду

PIN_WRITE(D, 3, LOW);
PIN_MODE(D, 3, OUTPUT_MODE);

т.е. устанавливаем третий пин порта D в режим выхода PUSH-PULL для работы на частотах до 10 мгц.

А можно эти 10мгц убрать и установить частотный потолок до 2мгц

PIN_MODE(D, 3, OUTPUT_MODE - HIGH_SPEED);

Или PUSH-PULL заменить открытым стоком

PIN_MODE(D, 3, OUTPUT_MODE - PUSH_PULL);

Такая форма записи описывает все возможные режимы работы пина, причем это можно сделать несколькоими способами. Записи вида

PIN_MODE(D, 3, OUTPUT + OPEN_DRAIN + LOW_SPEED);

и

PIN_MODE(D, 3, OUTPUT_MODE - PUSH_PULL - HIGH_SPEED);

полностью эквивалентны.

Наконец, я проверил, одинаковый ли код получается после компиляции, когда используется обычная "портяночная" запись и конфигурирование с помощью макроса. Для этого я компилятору с отключенной оптимизаций скормил следующий фрагмент:

  // CSN pin, default is high
  
  PIN_WRITE(D, 2, HIGH);
  PIN_MODE(D, 2, OUTPUT + PUSH_PULL + HIGH_SPEED);
  
  PD_ODR_ODR2 = 1;
  PD_DDR_DDR2 = 1;        //  Port D, bit 2 is output.
  PD_CR1_C12 = 1;         //  Pin is set to Push-Pull mode.
  PD_CR2_C22 = 1;         //  Pin can run up to 10 MHz.

Сначала второй пин порта D конфигурируется макросом, а потом "по старинке". Код получился одинаковым полностью.

    406            // CSN pin, default is high
    407            
    408            PIN_WRITE(D, 2, HIGH);
   \   000042 7214 500F    BSET      L:0x500f, #0x2
    409            PIN_MODE(D, 2, OUTPUT + PUSH_PULL + HIGH_SPEED);
   \   000046 7214 5011    BSET      L:0x5011, #0x2
   \   00004A 7214 5012    BSET      L:0x5012, #0x2
   \   00004E 7214 5013    BSET      L:0x5013, #0x2
    410            
    411            PD_ODR_ODR2 = 1;
   \   000052 7214 500F    BSET      L:0x500f, #0x2
    412            PD_DDR_DDR2 = 1;        //  Port D, bit 2 is output.
   \   000056 7214 5011    BSET      L:0x5011, #0x2
    413            PD_CR1_C12 = 1;         //  Pin is set to Push-Pull mode.
   \   00005A 7214 5012    BSET      L:0x5012, #0x2
    414            PD_CR2_C22 = 1;         //  Pin can run up to 10 MHz.
   \   00005E 7214 5013    BSET      L:0x5013, #0x2

Ну и можно глянуть, что получается при конфигурировании пина в режиме входа:

    358            PIN_MODE(C, 4, INPUT_MODE - PULL_UP + INT);
   \                     initGPIO:
   \   000000 7219 500C    BRES      L:0x500c, #0x4
   \   000004 7219 500D    BRES      L:0x500d, #0x4
   \   000008 7218 500E    BSET      L:0x500e, #0x4

Макрос PIN_MODE во всех случаях разворачивается в три команды манипуляций с отдельным битом в трех регистрах, отвечающих за режим работы пина.

В конце концов я переписал инициализацию пинов данными макросами в свой рабочий код приемника NRF24L01 и разницы в работе не отметил. Инициализация же при этом стала более компактной и более читабельной.

Кто всю эту хрень прочитал и хоть чего-нибудь понял, тот молодец. :)