STM32 F103C8T6

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Или надо менять IDE?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Всё, нашол сам достаточную инфу на Хабре. 

Юрий48
Offline
Зарегистрирован: 19.06.2018

Программировал с помощью ST-Link.

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

dimax, а если установить в IDE плату LeafLabs, она падёть для BluePill на STM32F103С8T6, или под нее другое что-то в boards.txt

Деда, в Иде есть непосредственно  BluePill , , на нее только загрузчик надо установить

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

да, спасибо, я почитал уже.  ничо там сложного

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

dimax пишет:

5N62V, да, я тоже невнимательно посмотрел. Не Output. Но всё равно косяк ваш есть. Посмотрите на reset defaults -там бит CNF0 уже стоит. Командой |= вы к нему подписываете ещё и CNF1, получается недокументированная комбинация в регистре CRL *1100


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

Юрий48
Offline
Зарегистрирован: 19.06.2018

dimax пишет:

Юрий48, работать с стм32 под ардуино IDE конечно просто, но есть свои особенности. Многие ключевые вещи описаны в документации.  В команде pinMode например существенные отличия. Но это всё сразу видно.  А есть вещи, которые описаны, но найти это описание не так то просто. Вот взять I2C. Их на плате 2шт +  один из них можно ремапнуть на другие порты. Соответссно есть специальные функции, которые нужно выполнить для инициализации нужного порта. Вы ведь  не инициализировали I2C перед тем, как с ним работать?  :) И это ещё не всё, в аддоне стм32 используется своя библиотека wire(), она совместима с обычной, но всё таки есть небольшие нюансы.

Сейчас мне уж не до I2C поскольку тривиальный пример Blink не работает. Всё делалось по инструкции  именно для этой платы. Можно ли сформулировать конкретную последовательность действий для приведения её в чувство?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Юрий48, вы недостаточно подробно изложили исходные данные. Какой конкретно скетч вы загружаете, какие опции выбора мк в меню (плата, частота, метод загрузки)  успешно ли происходит прошивка.

nik182
Offline
Зарегистрирован: 04.05.2015

Программу блинка опубликуйте. D13 соединённый со светодиодом на плате отсутствует.

Юрий48
Offline
Зарегистрирован: 19.06.2018

dimax пишет:

Юрий48, вы недостаточно подробно изложили исходные данные. Какой конкретно скетч вы загружаете, какие опции выбора мк в меню (плата, частота, метод загрузки)  успешно ли происходит прошивка.

Использовал arduino1.8.5 с Arduino_STM32-master именно под arduino1.8.х. Правда в инете пишут, что рабочия версия для STM32 - ардуино1.6.9. Мне подумалось, что это устаревшая информация поскольку есть библиотеки для 1.8.х. Справедливости ради попробовал и в arduino1.6.9, но результат не изменился.

Настройки

1. плата Generic STM32F103C Series

2. частота 72 мГц

3. метод загрузки STLink

4. оптимизация -01

5. оба бота в 0

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin PB1 as an output.
  pinMode(PB13, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(PB13, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(PB13, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second
}

32-bits ARM Cortex-M3 инициализирован. Компиляция проходит успешно. В конце строка "Application started."

Что происходит при заливке? Новая программа затирает старую или пишется на новое место? То есть нужно ли предварительно стирать старую?

И вообще как понять, 1. что загрузилось то, что нужно 2. как ведёт себя программа при реальной работе. Правильно я понимаю, что второй пункт не для ардуино?

b707
Offline
Зарегистрирован: 26.05.2017

Юрий48, если плата вот такая

то на ней порт светодиода - РС13, а не PB13, как написано у вас в коде

Кстати, там на плате даже подписано - посмотрите

Юрий48
Offline
Зарегистрирован: 19.06.2018

b707, спасибо плата такая, исправил и заработало. Вобщем из разряда "сам дурак". Обидно, поскольку такие ошибки мне не свойственны. Ну, что ж, теперь можно замахнуться и на I2C.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016
b707
Offline
Зарегистрирован: 26.05.2017

Юрий48 пишет:

 теперь можно замахнуться и на I2C.

что там замахиваться-то? одна из I2C в "голубой таблетке" отлично управляется напрямую из Ардуино ИДЕ, синтаксис полностью аналогичен "родным" ардуиновским библиотекам. Когда мы с sadman41 тестировали Епромку FM24 - я его код для Атмеги просто перетащил в СТМ32-дуино практически без правки.

Юрий48
Offline
Зарегистрирован: 19.06.2018

Я эту фразу и имел ввиду. Что касается самого коментария, то из этого же фильма подойдёт немного перефразированна цитата "Это нога какая не надо нога." Пожалуй, эта фраза подошла бы и к моей ошибке с ногой в предыдущих постах. Но, это так,  ради шутки.

Ура, индикатор задышал. Дело было в неправильном адресе у-ва I2C. Стоял 0x27, а надо было 0x3F.

b707 пишет:

что там замахиваться-то? одна из I2C в "голубой таблетке" отлично управляется напрямую из Ардуино ИДЕ, синтаксис полностью аналогичен "родным" ардуиновским библиотекам. Когда мы с sadman41 тестировали Епромку FM24 - я его код для Атмеги просто перетащил в СТМ32-дуино практически без правки.

Хотя индикатор и зарабртал, но меня заинтересовал вопрос: "Каким образом программа узнала, что надо работать именно с теми ножками I2C, которые соответствуют данному процессору?" Ведь она же универсальная. Пока делаю вывод, что та библиотека, которую я использую, заточена именно под STM32F103C

b707
Offline
Зарегистрирован: 26.05.2017

Юрий48 пишет:

"Каким образом программа узнала, что надо работать именно с теми ножками I2C, которые соответствуют данному процессору?" Ведь она же универсальная. Пока делаю вывод, что та библиотека, которую я использую, заточена именно под STM32F103C

вы же указываете в настройках Ардуино ИДЕ тип платы и процессора. В соответсвии с этими настройками из библиотеки выбирается код, относящихся именно к этому процессору.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

b707, думаю Юрий имел ввиду как программа выбрала нужный вариант подключения I2C , их там 3. Видимо есть инициализация по-умолчанию. Типа первый i2c на основных пинах по умолчанию, а что б выбрать другой нужно вызывать соответствующие функции.

Юрий48
Offline
Зарегистрирован: 19.06.2018

Вопрос возник такой. Как в ардуино для STM32 конфигурировать режимы входов-выходов? Их же там 6 не считая альтернативных. Хотелось бы иметь список команд или описание как это делать.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

 Юрий48,  то есть ссылку на документацию, что я давал вы не открывали..

Юрий48
Offline
Зарегистрирован: 19.06.2018

dimax пишет:

 Юрий48,  то есть ссылку на документацию, что я давал вы не открывали..

Спасибо за ссылку. Открывал, но не разбирался. Сейчас заставили посмотреть повнимательней. С помощью переводчика разобрался в функции pinMode(). Хотя это не очень то удобно.

b707
Offline
Зарегистрирован: 26.05.2017

Юрий48 пишет:

Хотя это не очень то удобно.

что именно? - разбираться переводчиком? -учите английский, всяко полезно.

Юрий48
Offline
Зарегистрирован: 19.06.2018

b707 пишет:

что именно? - разбираться переводчиком? -учите английский, всяко полезно.

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

Юрий48
Offline
Зарегистрирован: 19.06.2018

Совсем задолбался с тривиальщиной. Не правильно выводится переменная i - должна постоянно увеличиваться в соответствии с инкрементом. Время на дисплее как и положено меняется, а переменная i - нет. Выводится значение инкремента, в данном случае 7, и не меняется. На бессмысленное в данном примере условие не обращайте внимание.

[code]
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3F, 16, 2);  // Set the LCD address to 0x27 for a 16 chars and 2 line display
char output_string[18];       // Строка вывода на дисплей

void setup()
{ 
  // initialize the LCD
  lcd.begin();
  lcd.backlight();
  }

void loop()
{
  unsigned long Ost;            // Время до окончания процесса, сек
  unsigned long T_msK;          // Текущее системное время, ms
  int i;
  
   if (T_msK <= millis())  // Обработка состояния кнопок кажные 100 ms
   {
   i = i + 7;
   lcd.setCursor(0, 0);
   sprintf ( output_string, "%4i", i);
   lcd.print(output_string);
   Ost = millis()/1000;
   sprintf ( output_string, "%01i:%02i:%02i", Ost/3600, Ost%3600/60, Ost%60);
   lcd.setCursor(0, 1);
   lcd.print(output_string);
   }
   delay(2000);
}

[/code]

 

Юрий48
Offline
Зарегистрирован: 19.06.2018

Вышел из этого клинча, но без понятия. Переменную i определил как глобальную и всё адекватно заработало. Поясните, пожалуйста, почему в данном примере она не хотела работать как локальная. Казалось бы за рамки цикла loop(), где она определена, она не выходит.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Когда выполнение уходит из loop(), значение локальной переменной теряетса, что непонятного?

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

К Ost и T_msk  это тоже относится. 

Kost286
Offline
Зарегистрирован: 20.09.2016

или так

03 #include <LiquidCrystal_I2C.h>
04 #include <Wire.h>
05 LiquidCrystal_I2C lcd(0x3F, 16, 2);  // Set the LCD address to 0x27 for a 16 chars and 2 line display
06 char output_string[18];       // Строка вывода на дисплей
07  
17   unsigned long Ost;            // Время до окончания процесса, сек
18   unsigned long T_msK;          // Текущее системное время, ms
19   int i;
08 void setup()
09 {
10   // initialize the LCD
11   lcd.begin();
12   lcd.backlight();
13   }
14  
15 void loop()
16 {
20   
21    if (T_msK <= millis())  // Обработка состояния кнопок кажные 100 ms
22    {
23    i = i + 7;
24    lcd.setCursor(0, 0);
25    sprintf ( output_string, "%4i", i);
26    lcd.print(output_string);
27    Ost = millis()/1000;
28    sprintf ( output_string, "%01i:%02i:%02i", Ost/3600, Ost%3600/60, Ost%60);
29    lcd.setCursor(0, 1);
30    lcd.print(output_string);
31    }
32    delay(2000);
33 }

 

Юрий48
Offline
Зарегистрирован: 19.06.2018

DetSimen пишет:

Когда выполнение уходит из loop(), значение локальной переменной теряетса, что непонятного?

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

К Ost и T_msk  это тоже относится. 

Спасибо. В чём принципиальная разница в объявлении переменной  как глобальной или её объявление как локальной с модификатором static?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

в том, что static видит только та функция, в которой переменная обьявлена, а простую глобальную переменную могут видеть (и изменить неожыданна) все кому не лень в этом модуле.  А при некоторых условиях - и в других модулях.  Читать про "области видимости". 

Юрий48
Offline
Зарегистрирован: 19.06.2018

Написал обработчик кнопок. Работает адекватно. Но, вот, никак не могу разобраться, как правильно добавить в функцию переменную, отвечающую за пины, к которым подключены кнопки. В данном случае для отладки у меня  статично подключён пин PB1. А надо, что бы в функцию передавался произвольный.

/*Функция обработки нажатия кнопки. Возвращает значение статуса нажатия кнопки,
  0 - не нажата, 1 - короткое нажатие, 2 - продолжительное нажатие */
  char obrKnopk (int Short_Knopk, int Long_Knopk)
    {
     char Knopk; 
       if (digitalRead(PB1) == HIGH) 
           Count_Knopk  ++;
        else 
           Count_Knopk  --;
           
       Count_Knopk = constrain(Count_Knopk, 0, Long_Knopk);
        Max_Knopk = max(Max_Knopk, Count_Knopk);
       if (Count_Knopk == 0)
          {
            if ((Max_Knopk < Short_Knopk) && !Long_Push)
                {Knopk = 0; Max_Knopk = 0;}
              else if ((Short_Knopk <= Max_Knopk < Long_Knopk) && !Long_Push)
                {Knopk = 1; Max_Knopk = 0;}
              else if (Long_Push)
                {Knopk = 0; Max_Knopk = 0; Long_Push = false;}
              else {}
          }
        else if ((Max_Knopk == Long_Knopk) && !Long_Push)
              {Knopk = 2; Long_Push = true;}
        else {}      
       return (Knopk);
       //return (2);
    }

 

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015
  char obrKnopk (int Short_Knopk, int Long_Knopk, int Pin)
    {
     char Knopk; 
       if (digitalRead(Pin) == HIGH) 
           Count_Knopk  ++;
        else 
           Count_Knopk  --;

 

Юрий48
Offline
Зарегистрирован: 19.06.2018

xDriver пишет:

  char obrKnopk (int Short_Knopk, int Long_Knopk, int Pin)
    {
     char Knopk; 
       if (digitalRead(Pin) == HIGH) 
           Count_Knopk  ++;
        else 
           Count_Knopk  --;

А что записывать в Pin именно для STM32? Не PB1 же, в int это не записать. Может, порядковый номер ножки?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Юрий48, это объявление функции в io.h

void pinMode(uint8 pin, WiringPinMode mode);

Как видите имя пина функция кладёт в 8-битнуб переменную, почему вам это нельзя сделать? :)

b707
Offline
Зарегистрирован: 26.05.2017

Юрий48 пишет:

А что записывать в Pin именно для STM32? Не PB1 же, в int это не записать.

PB1 - это макрос, то же самое как

#define RELAY_PIN 12

поэтому его запросто можно использовать там, где нужен int

Юрий48
Offline
Зарегистрирован: 19.06.2018

dimax и b707, спасибо. Про макрос как то и не подумал.

Юрий48
Offline
Зарегистрирован: 19.06.2018

Поясните, пожалуйста. Когда пишу так

if ((Krit_Knop[0] <= Max_Knopk) && ( Max_Knopk < Krit_Knop[1]) && !Long_Push)

Всё работает адекватно, но когда пишу так

if ((Krit_Knop[0] <= Max_Knopk < Krit_Knop[1]) && !Long_Push)

результат фальшивый. В чём причина? Казалось бы совершенно одинаковые логические конструкции.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Это Вам только кажется.

Юрий48
Offline
Зарегистрирован: 19.06.2018

andriano пишет:

Это Вам только кажется.

В частности мне кажется Вы что то знаете очень интересное для меня, но по каким то соображениям хотите подразнить меня.

b707
Offline
Зарегистрирован: 26.05.2017

Юрий48 пишет:

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

абсолютно разные. Во втором случае полный бред написан

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Хорошо, поусть a = 9, b = 8, c = 7.

Значение выражения (a < b) && (b < c) очевидно сводится к 0 && 0 т.е. равно 0.

Значение выражения (a < b < c) очевидно сводится к (0 < c) т.е. равно 1.

 
Юрий48
Offline
Зарегистрирован: 19.06.2018

b707 пишет:

Юрий48 пишет:

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

абсолютно разные. Во втором случае полный бред написан

Бред с точки зрения синтаксиса? То есть такая конструкция для языка СИ не правомерна, но он же её проглотил.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Язык Си пропускет довольно большое количество разнообразных конструкций. Приведенная Вами - совершенно нормальная конструкция, но у меня складывается подозрение, что Вы не понимаете, как она работает.

Юрий48
Offline
Зарегистрирован: 19.06.2018

andriano пишет:

Хорошо, поусть a = 9, b = 8, c = 7.

Значение выражения (a < b) && (b < c) очевидно сводится к 0 && 0 т.е. равно 0.

Значение выражения (a < b < c) очевидно сводится к (0 < c) т.е. равно 1.

Спасибо, понятно. Действия выполняются последовательно по мере поступления новых.

b707
Offline
Зарегистрирован: 26.05.2017

Юрий48 пишет:

Бред с точки зрения синтаксиса? То есть такая конструкция для языка СИ не правомерна, но он же её проглотил.

с точки зрения синтаксиса как раз нормально. Это тоже самое, как известная фраза "Гло́кая ку́здра ште́ко будлану́ла бо́кра и курдя́чит бокрёнка" - синтаксис языка соблюден, но смысла никакого.

Так и у вас.

Юрий48
Offline
Зарегистрирован: 19.06.2018

b707 пишет:

Юрий48 пишет:

Бред с точки зрения синтаксиса? То есть такая конструкция для языка СИ не правомерна, но он же её проглотил.

с точки зрения синтаксиса как раз нормально. Это тоже самое, как известная фраза "Гло́кая ку́здра ште́ко будлану́ла бо́кра и курдя́чит бокрёнка" - синтаксис языка соблюден, но смысла никакого.

Так и у вас.

В общем я понял что к чему. Думаю, что полного бреда в такой записи нет. Наверняка можно её использовать в каких ни будь случаях.

b707
Offline
Зарегистрирован: 26.05.2017

Юрий48 пишет:

В общем я понял что к чему. Думаю, что полного бреда в такой записи нет. Наверняка можно её использовать в каких ни будь случаях.

ну, точно как с "глокой куздрой" - фраза бредовая, а вот пригодилась :)

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

Kost286
Offline
Зарегистрирован: 20.09.2016

логические операции в вашем случае это >, <, = не погут быть более одного раза повторёнными в одной конструкции без явного указания на каждую из них. Сравнивать можно лишь 2 значения между собой. Эти пары нужно брать в скобки, говоря компилятору, что сравнивать нужно именно эти пары, а потом результат сравнения вот с этим. Иначе приорител у них одинаковый и компилятор не знает с чего начать. Он же не видит кто стоит первым а кто вторым и .т.д.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Kost286 пишет:

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

Сам понял, что написал?

Цитата:

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

Выбросьте этот компилятор. Возьмите тот, который знает, с чего начать.

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

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

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Си - язык со слабой типизацией.

В Паскале бы не прошло сравнивать true с единицей, а Си - позволяет. (кстати, именно поэтому логические и битовые операции в Паскале обозначаются одинаково, а в Си - по-разному. Потому, что Си не различает логические и целые - для него это одно и то же)

Поэтому при вычислении цепочки сначала вычисляется значение первого выражения, которое может оказаться либо 0, либо 1. Затем полученное значение сравнивается со следующим и т.д.

sadman41
Offline
Зарегистрирован: 19.10.2016

a5021 пишет:

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

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