1 Востаннє редагувалося taburyak (24.07.2018 20:46:05)

Тема: STM32, Atolic TrueStudio, CubeMX

Започаткую я таку тему. Бо питання будуть виникати постійно. Десь маю я їх (питання) ставити :) Може, як повезе, то й отримаю відповіді :)

Перше питання з яким самотужки не впорався, це коли почав розбиратись з роботою цифрового термометру DS18b20 по шині 1-wire підключений до STM32F100RB по UART. Прикладів і бібліотек в мережі повно. Хоча я не зміг ними скористатись, бо готові проекти чимось не підходили, а бібліотеками я не зміг скористатись бо не знав як ними користуватись. Навіть в репозиторії CooCox'у є дві бібліотеки, одна від ST але наворочена занадто, інша простіша onewire з хорошим описом в статті  http://we.easyelectronics.ru/STM32/esch … vleno.html на початку статті є лінки на попередні статті присвячені цій бібліотеці. Вирішив взяти до свого проекту саме цю бібліотеку. Сам код бібліотеки мені зрозумілий і принцип роботи UART і 1-WIRE, як мені здається, в теорії розумію.
Розбирався, розбирався - безуспішно. І зрозумів, що я не розумію якусь річ зовсім не пов'язану з залізом і мовою С++.

Зараз спробую пояснити на прикладі. До цього, з метою самонавчання, зробив проект "Гра Хто Швидший" ось відео з макетом цієї гри https://www.youtube.com/watch?v=HSY1FD_Pkrs
Світлодіодами дригаємо, на кнопки реєгуємо, в біпер бібікаємо. Весь проект був складений з main.c плюс потрібні бібліотеки GPIO, RCC . Як бачите все працює.

Тепер до STM32 і DS18b20.
Як казав, що з готовими бібліотеками я не зміг розібратись, не розумію як ними користуватись. Створюю новий проект. Маю файл основного коду main.c і бібліотеку onewire.c, onewire.h. Компілятор зразу свариться на такі речі як unknown type name 'GPIO_InitTypeDef'. Ну як же ж не відомий як відомий.

Добре, думаю почну з нуля, створюю ще один новий проект. Який має такі файли:
main.c

#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_usart.h"
#include "ds18b20.c"

#define BAUDRATE 9600

int main(void){

while (1) {
}

}

і у вигляді окремої бібліотеки ds18b20.c

GPIO_InitTypeDef port;
USART_InitTypeDef usart;

void initUSART(){

//Вмикаємо тактування
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

//PA2 в режим альтернативних функцій USART TX
GPIO_StructInit(&port);
port.GPIO_Mode = GPIO_Mode_AF_PP;
port.GPIO_Pin = GPIO_Pin_2;
port.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &port);
//PA3 в режим альтернативних функцій USART RX
port.GPIO_Mode = GPIO_Mode_AF_PP;
port.GPIO_Mode = GPIO_Pin_3;
port.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &port);

USART_StructInit(&usart);
usart.USART_BaudRate = BAUDRATE;
USART_Init(USART2, &usart);

}

Та сама фішка при компіляції unknown type name 'GPIO_InitTypeDef'

Так, розумію що я щось не розумію саму суть бібліотек і їх структуру, бо коли я кидаю код що знаходився в файлі ds18b20 в основний код main.c, а файл ds18b20.c прибираю з проекту, то все компилиться без помилок.

#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_usart.h"

#define BAUDRATE 9600

GPIO_InitTypeDef port;
USART_InitTypeDef usart;

int main(void)
{

    void initUSART(){

    //Вмикаємо тактування
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    //PA2 в режим альтернативних функцій USART TX
    GPIO_StructInit(&port);
    port.GPIO_Mode = GPIO_Mode_AF_PP;
    port.GPIO_Pin = GPIO_Pin_2;
    port.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOA, &port);
    //PA3 в режим альтернативних функцій USART RX
    port.GPIO_Mode = GPIO_Mode_AF_PP;
    port.GPIO_Mode = GPIO_Pin_3;
    port.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOA, &port);

    USART_StructInit(&usart);
    usart.USART_BaudRate = BAUDRATE;
    USART_Init(USART2, &usart);

    }


    while(1)
    {
    }
}

Остаточно переконався що я не розумію якоїсь елементарної простої речі, якої я навіть не знаю як назвати, щоб пошукати і почитати про це. Ще звернув увагу, що в #include зазвичай файли з розширенням h, а там в основному #define всілякі. Проте є в проектах і однойменні файли з розширенням с, хоч ніяк не вкладаються.

Перепрошую за мабуть зовсім чайницькі питання. Але не відвертайтесь від мене. Без цієї дрібнички я не можу далі йти. Ну не робити ж проекти з одним main.c де весь код в купу накиданий.
Дякую.

Подякували: Betterthanyou, leofun01, NaharD, DW4

2 Востаннє редагувалося 0xDADA11C7 (23.10.2014 11:54:26)

Re: STM32, Atolic TrueStudio, CubeMX

спочатку скомпілюйте ds18b20.c, потім одержаний файл прилінкуйте до основного коду, попередньо під’єднавши заголовковий файл ds18b20.h

#include "ds18b20.h"
Подякували: taburyak1

3 Востаннє редагувалося taburyak (23.10.2014 18:59:13)

Re: STM32, Atolic TrueStudio, CubeMX

0xDADA11C7 написав:

спочатку скомпілюйте ds18b20.c, потім одержаний файл прилінкуйте до основного коду, попередньо під’єднавши заголовковий файл ds18b20.h

#include "ds18b20.h"

Дякую що відгукнулись. Мені це не дуже допомогло.
Зрозумів що я, на свій сором, не знаю як користуватись CooCox.

В описі CooCox є таке: "CoIDE автоматично створює всю структуру проекту, а також підключає всі інші необхідні для роботи бібліотеки. Кожна з них містить кілька готових прикладів, які можна використовувати в проекті. Є функція поповнення бібліотек власними прикладами. При підключенні нових бібліотек до проекту враховуються всі залежності між ними."

З цим зрозуміло. Це так. Стандартні бібліотеки, такі як GPIO, USART, TIM, RTC, тощо, підключаються без проблем з урахуванням залежностей. З якимись іншими які я пробував onewire чи wh1602 нічого не вийшло. Запустити WH1602 в мене таки вийшло, але коли я розташував код в основний файл main.c

Роблю так:
Створюю новий проект -> обираю свій чип -> обираю чекбоксики з потрібними стандартними бібліотеками (вони додаються до проекту) -> потім наприклад хочу створити свою бібліотеку з функціями роботи того чи іншого пристрою (ЖК екран чи термометр) -> клацаю ПКМ на структурі проекту, обираю новий файл, даю назву ds18b20.c -> заповнюю цей файл кодом який в файлі main.c компілюється аж бігом -> в файлі main.c пишу директиву #include "ds18b20.c" (директива вказує препроцесору, що вміст заданого файлу необхідно обробити так, як якщо б воно знаходилося в початковій програмі в тій точці, в якій розташовується ця директива) -> тисну Build F7 і помилки "2: error: unknown type name 'GPIO_InitTypeDef'", "2: error: unknown type name 'USART_InitTypeDef'" і таке інше. Типу бібліотека зовсім не приєдналась.

Раз це не працює, значить щось я роблю не правильно. Що саме? Я самотужки не можу розібратись. Допоможіть будь ласка.

4

Re: STM32, Atolic TrueStudio, CubeMX

Ваше IDE я встановлювати не збираюся, тож шукайте де воно викликає GCC із якими опціями компіляції - наприклад, особисто я, не користуюся жадним ІDE, а пришу .cmd чи .sh. У вашому випадку використовується компілятор ARM GCC 4.7.
Так ніхто не пише, бо це неправильно:

#include "ds18b20.c"

Підключаються в джерельному коді лише заголовкові файли, а об’єктні файли передаються лінкеру.
тобто у вашому випадку треба спочатку додати наступний рядок в main.c

#include "ds18b20.h"

скомпілювати main.c, потім скомпілювати ds18b20.c, а потім злінкувати обидва одержані від компілера файли в готовий бінарник. Якщо процесс незрозумілий - тренуйтеся на щурах на GCC для х86 архітектури. Тобто ваша проблема в нерозумінні принципів роботи компіляторів, а не ARM.

Подякували: taburyak, DOP, leofun013

5

Re: STM32, Atolic TrueStudio, CubeMX

Нарешті зміг добратись до форума.
Дякую за правильний напрямок думок.
Коли знаєш що шукати, то воно й знаходиться швидко.
Прочитав про розбивку проєкту на окремі файли. Спробував свій проект розбити. Все вийшло. Наче зрозумів.
Спробував під'єднати ту бібліотеку onewire що в мене не виходило, і о чудо, все вийшло. Компілятор проковтнув як слід.
Тепер розбираюсь як тою бібліотекою користуватись, але це вже деталі.
Дякую.

Подякували: 0xDADA11C71

6

Re: STM32, Atolic TrueStudio, CubeMX

Вітаю!
Знову застопорився з цією бібліотекою onewire.
Бібліотека з репозиторію CooCox, приклад брав робочий. Все має працювати. Але мої початкові знання в С++ не дають зрозуміти ось це:
Є процедура яка приймає такі дані:

uint8_t OW_Send(uint8_t sendReset, uint8_t *command, uint8_t cLen, uint8_t *data, uint8_t dLen, uint8_t readStart);

А є виклик цієї процедури, спочатку даємо команду термометру "міряти", потім даємо час на роздуми сенсору і забираємо результат в buf:

int main(void)
{
    OW_Init();

    OW_Send(OW_SEND_RESET, "\xcc\x44", 2, NULL, NULL, OW_NO_READ);

    uint32_t i;
    for (i=0; i<1000000; i++);

    uint8_t buf[2];
    OW_Send(OW_SEND_RESET, "\xcc\xbe\xff\xff", 4, buf, 2, 2);

    while(1)
    {
    }
}

Де "\xcc\x44" і "\xcc\xbe\xff\xff" це послідовність команд для сенсора.
Це взято з прикладу. Компілятор хоч і компілює, але є зауваження, яких я не розумію. Допоможіть. Хочу розібратись. Зауваження від компілятора під спойлером.

Прихований текст

D:\CooCox\CoIDE\workspace\DS18B20\main.c: In function 'main':
       [cc] D:\CooCox\CoIDE\workspace\DS18B20\main.c:14:2: warning: pointer targets in passing argument 2 of 'OW_Send' differ in signedness [-Wpointer-sign]
       [cc]   OW_Send(OW_SEND_RESET, "\xcc\x44", 2, NULL, NULL, OW_NO_READ);
       [cc]   ^
       [cc] In file included from D:\CooCox\CoIDE\workspace\DS18B20\main.c:8:0:
       [cc] D:\CooCox\CoIDE\workspace\DS18B20\onewire.h:42:9: note: expected 'uint8_t *' but argument is of type 'char *'
       [cc]  uint8_t OW_Send(uint8_t sendReset, uint8_t *command, uint8_t cLen, uint8_t *data, uint8_t dLen, uint8_t readStart);
       [cc]          ^
       [cc] D:\CooCox\CoIDE\workspace\DS18B20\main.c:14:2: warning: passing argument 5 of 'OW_Send' makes integer from pointer without a cast [enabled by default]
       [cc]   OW_Send(OW_SEND_RESET, "\xcc\x44", 2, NULL, NULL, OW_NO_READ);
       [cc]   ^
       [cc] In file included from D:\CooCox\CoIDE\workspace\DS18B20\main.c:8:0:
       [cc] D:\CooCox\CoIDE\workspace\DS18B20\onewire.h:42:9: note: expected 'uint8_t' but argument is of type 'void *'
       [cc]  uint8_t OW_Send(uint8_t sendReset, uint8_t *command, uint8_t cLen, uint8_t *data, uint8_t dLen, uint8_t readStart);
       [cc]          ^
       [cc] D:\CooCox\CoIDE\workspace\DS18B20\main.c:20:2: warning: pointer targets in passing argument 2 of 'OW_Send' differ in signedness [-Wpointer-sign]
       [cc]   OW_Send(OW_SEND_RESET, "\xcc\xbe\xff\xff", 4, buf, 2, 2);
       [cc]   ^
       [cc] In file included from D:\CooCox\CoIDE\workspace\DS18B20\main.c:8:0:
       [cc] D:\CooCox\CoIDE\workspace\DS18B20\onewire.h:42:9: note: expected 'uint8_t *' but argument is of type 'char *'
       [cc]  uint8_t OW_Send(uint8_t sendReset, uint8_t *command, uint8_t cLen, uint8_t *data, uint8_t dLen, uint8_t readStart);

7

Re: STM32, Atolic TrueStudio, CubeMX

Вперше бачу цю бібліотеку, але там всюди використовується тип uint8_t, який, вочевидь, є синонімом до unsigned char; ви ж передаєте параметрами char * (вираз в лапках) і void * (NULL). А ще п'ятий параметр має бути int, ви ж передаєте void *. Звісно, там всюди очевидні перетворення, тому це не помилки, але компілятор дивується, чому ви так робите. Спробуйте щось на кшталт

OW_Send( OW_SEND_RESET, (uint8_t *)"\xcc\x44", 2, (uint8_t *)NULL, 0, OW_NO_READ );
Подякували: taburyak1

8

Re: STM32, Atolic TrueStudio, CubeMX

koala

Дякую, так скомпілювало без проблем.

З п'ятим параметром зрозумів. Ось такий запис десь вже бачив  (uint8_t *)"\xcc\x44" та не звернув уваги бо не розумів. Що він означає?

Важко дається мені С++, треба процедурі PrintStr виводу тексту на РК екранчик, якось дати числові змінні, читав читав про перетворення та спеціяльні функції нічого не виходить в мене.

void PrintStr(char *Text)
{
    char *c;
    c = Text;
    while ((c != 0) && (*c != 0))
    {
        SendByte(*c, 1);
        c++;
    }
}

ось так пропонують зробити саме для цієї функції
int i=123;
char *t;
snprintf(t, 255, "%d", i);
PrintStr(t);

Під спойлером як компілятор свариться на мене.

Прихований текст

arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -Wall -ffunction-sections -g -O0 -c -DSTM32F100RB -DSTM32F10X_MD_VL -DUSE_STDPERIPH_DRIVER -D__ASSEMBLY__ -DSUPPORT_CPLUSPLUS -ID:\CooCox\CoIDE -ID:\CooCox\CoIDE\workspace\WH1602A\cmsis -ID:\CooCox\CoIDE\workspace\WH1602A\cmsis_boot -ID:\CooCox\CoIDE\workspace\WH1602A\stm_lib -ID:\CooCox\CoIDE\workspace\WH1602A\stm_lib\inc -ID:\CooCox\CoIDE\workspace\WH1602A -ID:\CooCox\CoIDE\workspace D:\CooCox\CoIDE\workspace\WH1602A\main.c
       [cc] D:\CooCox\CoIDE\workspace\WH1602A\main.c: In function 'main':
       [cc] D:\CooCox\CoIDE\workspace\WH1602A\main.c:13:10: warning: 't' is used uninitialized in this function [-Wuninitialized]
       [cc]   snprintf(t, 255, "%d", i);
       [cc]           ^
       [cc] 200
       [cc] Starting link
       [cc] arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -g -Wl,-Map=WH1602A.map -O0 -Wl,--gc-sections -LD:\CooCox\CoIDE\configuration\ProgramData\WH1602A -Wl,-TD:\CooCox\CoIDE\configuration\ProgramData\WH1602A/arm-gcc-link.ld -g -o WH1602A.elf ..\obj\startup_stm32f10x_md_vl.o ..\obj\system_stm32f10x.o ..\obj\stm32f10x_gpio.o ..\obj\main.o ..\obj\stm32f10x_rcc.o -lstdc++
       [cc] c:/program files (x86)/gnu tools arm embedded/4.8 2014q3/bin/../lib/gcc/arm-none-eabi/4.8.4/../../../../arm-none-eabi/lib/armv7-m\libg.a(lib_a-sbrkr.o): In function `_sbrk_r':
       [cc] sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk
       [cc] '
       [cc] collect2.exe: error: ld returned 1 exit status

BUILD FAILED
Total time: 1 second

9 Востаннє редагувалося koala (12.11.2014 16:45:23)

Re: STM32, Atolic TrueStudio, CubeMX

taburyak написав:

Ось такий запис десь вже бачив  (uint8_t *)"\xcc\x44" та не звернув уваги бо не розумів. Що він означає?

Приведення типів. Запис

назва_типу(вираз)

або

(назва_типу)вираз

означає, що "вираз" буде перетворено на тип "назва_типу" (наприклад, int(1.23) == 1)

taburyak написав:


Важко дається мені С++, треба процедурі PrintStr виводу тексту на РК екранчик, якось дати числові змінні, читав читав про перетворення та спеціяльні функції нічого не виходить в мене.

int i=123;
char *t;
snprintf(t, 255, "%d", i);
PrintStr(t);

char array[256]; - масив з 256 елементів типу char
char *pointer; - вказівник на char
І array, і pointer можна використовувати (практично) однаково в виразах, де потрібен char *; але array вказує на область пам'яті з 256 елементів, а для pointer ми ще нічого не виділили, і вказує він аби-куди. Щоб можна було писати за адресою в pointer (що й робить snprintf), треба виділити йому пам'ять - як мінімум,
pointer = array;//тепер pointer вказує на массив
або функціями malloc/calloc.

Другий параметр snprintf, до речі, задає обмеження - якщо буде записано 255 char-ів, snprintf завершиться незалежно від того, все він вивів чи ще ні. Якщо вказати більше число, ніж виділено пам'яті, то він буде писати, знову ж таки, аби-куди...

Подякували: taburyak, DW2

10

Re: STM32, Atolic TrueStudio, CubeMX

Дякую за допомогу.
Потроху рухаюсь вперед.
І знову є питання.
Все та ж плата з STM32F100RB плюс сенсор температури DS18B20 плюс індикатор РК WH1602.
Вже міряю температуру і виводжу все то на екранчик.

Тепер в чому проблема.
Є бібліотека onewire яка працює з пристроями по 1-wire протоколу з різними корисними процедурами.
Є декілька сенсорів температури. В кожного сенсора температури є свій унікальний ID пристрою. Якщо пристроїв на лінії аж одна штука, то немає питань, звертаємось до нього як до єдиного і отримую температуру. Але як їх декілька, то треба звертатись до них по ID бо сидять на одній лінії і треба ж до кожного окремо звертатись щоб не було колізій.
Робиться це так:

OW_Init(); //процедура ініціалізації
    uint8_t NumID;//змінна де буде кількість сенсорів на лінії
    uint8_t bufID[16];//масив де будуть ID пристроїв, по 8 байтів на пристрій (тут масив для двох пристроїв)
    NumID=OW_Scan((uint8_t *)bufID,2);//звертаємось до процедури сканування лінії, яка поверне кількість пристроїв та їх ID запише в масив
uint8_t buf[2];//тут будемо зберігати показники температури які зчитаємо з сенсора 
//звертаємось до процедури яка дасть команду міряти конкретному сенсору температуру і забере результат вимірювань
OW_Send(OW_SEND_RESET,(uint8_t *) "\x55\x28\xF8\xFB\xE1\x01\x00\x00\x76\xbe\xff\xff", 12, buf, 2, 10);

Тепер пояснюю що мені не зрозуміло.
Тут в прикладі рядку 7 наведено виклик процедури з параметрами "\x55\28\xF8\xFB\xE1\x01\x00\x00\x76\xbe\xff\xff" де - x55 пошук пристрою по ID, сам ID x28 xF8 xFB xE1 x01 x00 x00 x76, xBE команда на зчитування з регістру пристрою.
І тут в рядку 7 прикладу ID пристрою вказується в лоб, так неначе я вже його завчасно знаю. А мені треба щоб ID пристрою бралось з масиву bufID в якому вже є 8 байт з ID пристроєм.
Я не розумію як викликати процедуру OW_Send щоб послати команду x55 bufID (з 0 по 7 індекс) xbe xff xff
Теоретично думаю, що треба скласти ті всі команди і ID в якийсь окремий масив з 12 байтів і той масив вже якось в процедуру вставити. Але я в Сі початківець і не можу зрозуміти як це зробити.
Допоможіть будь ласка.

11

Re: STM32, Atolic TrueStudio, CubeMX

Треба сформувати запит, правильно:

uint8_t query[12]={0x55, 0,0,0,0,0,0,0,0, 0xBE, 0xFF, 0xFF};
uint8_t bufID[2][8];
memcpy(&query[1], bufID[0], 8);//копіюємо 8 байт з bufID[0] до місця в пам'яті, що починається з query[1]
OW_Send(OW_SEND_RESET, query, 12, buf, 2, 10);

А ще краще - створити структуру для запиту, але це вже залежить від того, що там може бути в запиті.

Подякували: taburyak1

12

Re: STM32, Atolic TrueStudio, CubeMX

koala написав:

Треба сформувати запит, правильно:

uint8_t query[12]={0x55, 0,0,0,0,0,0,0,0, 0xBE, 0xFF, 0xFF};
uint8_t bufID[2][8];
memcpy(&query[1], bufID[0], 8);//копіюємо 8 байт з bufID[0] до місця в пам'яті, що починається з query[1]
OW_Send(OW_SEND_RESET, query, 12, buf, 2, 10);

А ще краще - створити структуру для запиту, але це вже залежить від того, що там може бути в запиті.

Красно дякую.
Зрозумів.
А в рядку 3 вашого прикладу чи не правильніше написати bufID[0][0]? бо вже є двомірним масивом. Чи запис bufID[0] теж є коректним як звертатись до [0][0]?

А можна приклад запиту структурою? Там всі елементи uint. Структуру в С++ погуглив для ознайомлення. Було б чудово нею оформити.

13

Re: STM32, Atolic TrueStudio, CubeMX

В С++ ім'я масиву переважно означає те саме, що й вказівник на його початковий елемент:

bufID[0] == &bufID[0][0]

memcpy потрібна адреса для копіювання, от і передаємо їй цю адресу.
Що ж до структур, то якщо всі запити містять по 12 байт і мають таку форму (Тип команди - ID - команда до 3-х байт), то
struct Query
{
  uint8_t type;
  uint8_t ID[8];
  uint8_t command[3];
};
...
Query getData;
getData.type = 0x55;
memcpy(getData.ID, bufID[3], sizeof(getData.ID) );
memcpy(getData.command, "\xbe\xff\xff", sizeof(getData.command) );
OW_Send(OW_SEND_RESET, &getData, sizeof(getData), buf, 2, 10);

Але виглядає, що там можуть бути різні довжини команд, тому треба щось інше.

Подякували: taburyak1

14

Re: STM32, Atolic TrueStudio, CubeMX

koala, велике дякую за пояснення. Мабуть таки з структурою в цьому випадку це вже зайві нагромадження. Там дійсно різна кількість команд і довжина різна використовується.
А ваш приклад в попередньому повідомленні дуже, як на мене, елегантний, і мені сподобалось таке рішення. Дякую.

15

Re: STM32, Atolic TrueStudio, CubeMX

Перепрошую.
Ще один нюанс.
Функція OW_scan повертає 8 бітний ID пристроїв в одномірний масив bufID і кількість пристроїв NumID.
Мені потім треба це розкласти в додатковий двомірний масив, типу отак?

for (i=0; i<NumID; i++)
for (j=0; j< 8; j++)
bufquery[i][j]=bufID[i*8+j];

Це я написав, як я розумію на свій досвід початківця. Чи може це робиться якось по іншому?

16

Re: STM32, Atolic TrueStudio, CubeMX

Та не обов'язково, можна і одновимірний використовувати, тоді в memcpy замість bufID[ i ] буде &bufID[ 8*i ] (адреса 8*i-го елемента).

17 Востаннє редагувалося taburyak (22.11.2014 13:09:46)

Re: STM32, Atolic TrueStudio, CubeMX

koala написав:

Та не обов'язково, можна і одновимірний використовувати, тоді в memcpy замість bufID[ i ] буде &bufID[ 8*i ] (адреса 8*i-го елемента).

О! І то вірно. Дякую. Такі речі мабуть з досвідом приходять.

З вашою допомогою вийшло в мене як слід. Програма вийшла доволі універсальною, сама сканує кількість сенсорів температури, визначає їх ID, дає команду всім міряти і по черзі забирає данні температури у кожного сенсора по ID і виводить то все на екран. Кількість сенсорів на лінії теж довільна (обмежено 5-ма сенсорами, не уявляю нащо більше знадобиться), щоб на гарячу можна було чи міняти сенсори чи зменшувати/збільшувати кількість.

Йдемо далі :)
Тепер треба годинник запустити.

18

Re: STM32, Atolic TrueStudio, CubeMX

Щось я не можу побороти одну проблему. Є два сенсора температури і коли виймаєш їх то замість показників температури має бути написочка "No Device". Це працює коли один сенсор встановлено. Але коли їх два, то замість "No Device" показує "-0.0 С". Десь помилився чи з умовою чи з циклом, не можу розібратись. Гляньте свіжим поглядом.

    while(1)
    {
        //Даємо команду всим сенсорам "міряй"
        OW_Send(OW_SEND_RESET,(uint8_t *) "\xcc\x44", 2,(uint8_t *) NULL, 0, OW_NO_READ);
           //Даємо час сенсору на вимірювання
           delay_ms(750);
        int i;
        for (i = 0; i < NumID; i++) {
            //Забираємо результат вимірювань у масив buf з двох байтів
            uint8_t buf[2];
            uint8_t query[12]={0x55, 0,0,0,0,0,0,0,0, 0xBE, 0xFF, 0xFF};
            memcpy(&query[1], &bufID[i*8], 8);//копіюємо 8 байт з bufID[0] до місця в пам'яті, що починається з query[1]
            lcd_goto(i+1,0);
            lcd_puts((uint8_t *)"Temp");//Вивід тексту на екран
            lcd_itos(i+1);//Вивід тексту на екран
            lcd_puts((uint8_t *)"= ");//Вивід тексту на екран
            lcd_goto(i+1,7);//Встановлення курсору в позицію
            if (OW_Send(OW_SEND_RESET, query, 12, buf, 2, 10)==OW_NO_DEVICE){
                lcd_puts((uint8_t *)"No Device")//якщо функція повертає "OW_NO_DEVICE" то друкуємо написочку "No Device"
            } else {
                //Визначаємо який знак у температури
                if ((buf[1]&0x80) != 0) {    //Перевіряємо старший розряд як не 0 то..
                    lcd_puts((uint8_t *)"-"); //ставимо знак -
                    unsigned int tmp;        //робимо потрібні перетворення з числом
                    tmp = ((unsigned int)buf[1]<<8)|buf[0]; //зліплюємо 0 і 1 байт ОЗУ сенсора
                    tmp = ~tmp + 1; //виконуємо операцію логіного заперечення
                    buf[0] = tmp; //повертаємо результат перетворення
                    buf[1] = tmp>>8;
                }
                    int T1 = ((buf[1]&7)<<4)|(buf[0]>>4);
                    lcd_itos(T1);//ціле на екран
                    T1 = (buf[0]&15);
                    T1 = (T1<<1) + (T1<<3);// Множимо на 10
                    T1 = (T1>>4);//ділимо на 16 або множимо на 0.0625
                    lcd_puts((uint8_t *)".");//кому на екран
                    lcd_itos(T1);//залишок на екран
                    lcd_putc(0);//спецсимвол на екран
                    lcd_puts((uint8_t *)"C");
                    lcd_puts((uint8_t *)"   ");
            }
    }
    }

19

Re: STM32, Atolic TrueStudio, CubeMX

Морочусь зараз з годинником реального часу RTC на STM32F100RB. Сам годинник запустити вдалось. Показує час, дату і працюють переривання кожної секунди. Але не розібрався з ALARM. Задаю в регістр ALR 10 секунд, йде рахунок 10 секунд, потім годинник зупиняється, хоч секундні переривання є, і програма йде в обробник переривань RTC_IRQHandler по секундам. А ось в обробник переривань RTCAlarm_IRQHandler не йде чогось.

Ось обробники переривань по секундам і по будильнику:

void RTCAlarm_IRQHandler(void)
{
    if(RTC_GetITStatus(RTC_IT_ALR) != RESET)
    {
        RTC_ClearITPendingBit(RTC_IT_ALR);
        RTC_WaitForLastTask();//чекаємо поки останні операції запису до RTC закінчаться
        LCD_PORT->BSRR = LED_GREEN;//Вмикаємо зелений світлодіод
    }
}

void RTC_IRQHandler(void)
{
    if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
    {
        RTC_ClearITPendingBit(RTC_IT_SEC);//очистити RTC переривання по секундам
        LCD_PORT->ODR ^= LED_BLUE;//перемикаємо стан голубого світлодіода
        RTC_WaitForLastTask();//чекаємо поки останні операції запису до RTC закінчаться
    }
}

А ось конфігурація переривань:

void NVIC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;

    /* Configure one bit for preemption priority */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

    /* Enable the RTC Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

А ось дозволяю переривання секундні та будильник:

RTC_ITConfig(RTC_IT_SEC, ENABLE);//Вмикаємо відлік RTC по секундам
RTC_SetAlarm(10);//Встановлюємо відлік будильника на 10 секунд
RTC_ITConfig(RTC_IT_ALR,ENABLE);//Вмикаємо відлік ALARM

Що не так?

20 Востаннє редагувалося VitekSVM (08.12.2014 19:18:10)

Re: STM32, Atolic TrueStudio, CubeMX

taburyak написав:

Щось я не можу побороти одну проблему. Є два сенсора температури і коли виймаєш їх то замість показників температури має бути написочка "No Device". Це працює коли один сенсор встановлено. Але коли їх два, то замість "No Device" показує "-0.0 С". Десь помилився чи з умовою чи з циклом, не можу розібратись. Гляньте свіжим поглядом.

    
          ...
            if (OW_Send(OW_SEND_RESET, query, 12, buf, 2, 10)==OW_NO_DEVICE){
                lcd_puts((uint8_t *)"No Device")//якщо функція повертає "OW_NO_DEVICE" то друкуємо написочку "No Device"
            } else {
                //Визначаємо який знак у температури
                if ((buf[1]&0x80) != 0) {    //Перевіряємо старший розряд як не 0 то..
                    lcd_puts((uint8_t *)"-"); //ставимо знак -
                    unsigned int tmp;        //робимо потрібні перетворення з числом
                    tmp = ((unsigned int)buf[1]<<8)|buf[0]; //зліплюємо 0 і 1 байт ОЗУ сенсора
                    tmp = ~tmp + 1; //виконуємо операцію логіного заперечення
                    buf[0] = tmp; //повертаємо результат перетворення
                    buf[1] = tmp>>8;
                }
                    ...
       

Значить коли відключені обидва датчики функція OW_Send повертає не OW_NO_DEVICE. Так що перевіряй на інші результати функції  OW_Send.

і ще :
  1. lcd_putc виконується швидше ніж lcd_puts
  2. lcd_itos повинна вміти виводи "-" перед від'ємними числами (по опису)

і мій варіант:

//Визначаємо який знак у температури
int T1;        //робимо потрібні перетворення з числом
T1 =(int) (((unsigned int)buf[1]<<8)|buf[0]); //зліплюємо 0 і 1 байт ОЗУ сенсора
if (T1 <0)
{
lcd_putc('-'); //ставимо знак -
T1 = -T1;  // від'ємне число стає додатнім
}

lcd_itos(T1>>4);//ціле на екран
lcd_putc('.');//кому на екран 
T1 = T1 & 15;
T1 = (T1<<1) + (T1<<3);// Множимо на 10
T1 = (T1>>4);//ділимо на 16 або множимо на 0.0625
lcd_itos(T1);//залишок на екран
lcd_putc(0);//спецсимвол на екран 
lcd_puts((uint8_t *)"C   ");

Подякували: 0xDADA11C7, taburyak2