Stm32 с чего начать изучение...
-
linkov1959
- Держит паяльник хвостом
- Сообщения: 923
- Зарегистрирован: Пн сен 10, 2018 19:16:28
Re: Stm32 с чего начать изучение...
ПростоНуб, ассемблер - это язык высокого уровня, "специалист" я программировал тумблерами, вводя двоичный код.
- Реклама
- ПростоНуб
- Собутыльник Кота
- Сообщения: 2723
- Зарегистрирован: Пт сен 07, 2018 20:20:02
- Откуда: деревня в Тульской губернии
Re: Stm32 с чего начать изучение...
linkov1959, сэр прямо извращенец. i8080 и Z80, когда еще не было ассеблера для ZX Spectrum, я программировал все равно на ассемблере, просто сделав себе макробиблиотеку кроссассемблера для ассемблера ЕС ЭВМ. Выводил на перфоленту, а с нее уже самодельным считывателем и ручным протягиванием перфоленты через него - прошивал РФ-ки.
Вот на EC 1033 тумблерами простейшие канальные программы вводил. Но там без вариантов было. Если система не грузится из-за зависшей дисковой стойки, то иначе ее не протолкнуть. А по питанию передергивать - себе дороже. Включение ЕС 1033 - это всегда была целая история, причем, нередко, с заменой сдохших при включении ТЭЗов. Потому месяцами не выключали ее. Когда появились ЕС-1035, ЕС-1045 и ЕС-1061 - это было уже счастье. У них уже был сервисный процессор, с которым можно было общаться через Consul или даже дисплей.
Вот на EC 1033 тумблерами простейшие канальные программы вводил. Но там без вариантов было. Если система не грузится из-за зависшей дисковой стойки, то иначе ее не протолкнуть. А по питанию передергивать - себе дороже. Включение ЕС 1033 - это всегда была целая история, причем, нередко, с заменой сдохших при включении ТЭЗов. Потому месяцами не выключали ее. Когда появились ЕС-1035, ЕС-1045 и ЕС-1061 - это было уже счастье. У них уже был сервисный процессор, с которым можно было общаться через Consul или даже дисплей.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Stm32 с чего начать изучение...
так я и потерял... профессионально (т.е. по должности) я программировал (недолго) еще в те времена, когда написание программ на ассемблере для MS DOS было вполне естественным... а потом увы.ПростоНуб писал(а):в IT, если даже всего год не учиться ничему новому, квалификацию теряешь заметно
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: Stm32 с чего начать изучение...
Мне вот ночью приснилось, что при выполнении кода из RAM, например, при отладке, сегмент данных находится сразу на своём месте
и его не надо копировать в стартапе. То есть, правильнее в стартапе вот так
Код: Выделить всё
.data :
{
. = ALIGN(4);
_sdata = .;
*(.data)
*(.data*)
. = ALIGN(4);
_edata = .;
} > SRAMКод: Выделить всё
#ifndef __DEBUG_SRAM__
extern uint32_t _sidata[], _sdata[], _edata[];
for (volatile uint32_t *pSrc = _sidata, *pDst = _sdata; pDst != _edata; *pDst ++= *pSrc++) ;
#endif-
linkov1959
- Держит паяльник хвостом
- Сообщения: 923
- Зарегистрирован: Пн сен 10, 2018 19:16:28
Re: Stm32 с чего начать изучение...
ПростоНуб, А ещё, извращенцы стирали РФки сваркой!
- Реклама
- ПростоНуб
- Собутыльник Кота
- Сообщения: 2723
- Зарегистрирован: Пт сен 07, 2018 20:20:02
- Откуда: деревня в Тульской губернии
Re: Stm32 с чего начать изучение...
linkov1959, тогда уж солнышком. Но некоторые пытались это делать через оконное стекло, забыв, что оно ультрафиолет не пропускает )))
Но это реально изврат, так как люминисцентные УФ лампы тогда были вполне доступны в продаже. Великоваты, конечно, так как предназначались для загара или в медицинских целях. Но вполне пригодны для стирания РФ-ок.
Но это реально изврат, так как люминисцентные УФ лампы тогда были вполне доступны в продаже. Великоваты, конечно, так как предназначались для загара или в медицинских целях. Но вполне пригодны для стирания РФ-ок.
Re: Stm32 с чего начать изучение...
Пробовал. Это долго. Понадобилось около 2-ух месяцев нахождения на солнце.ПростоНуб писал(а):тогда уж солнышком.
Лучше уж
linkov1959 писал(а):сваркой
- ПростоНуб
- Собутыльник Кота
- Сообщения: 2723
- Зарегистрирован: Пт сен 07, 2018 20:20:02
- Откуда: деревня в Тульской губернии
Re: Stm32 с чего начать изучение...
Мурик, в полярную ночь что ли пробовали или сквозь оконное стекло? В ясную погоду под летним крымским солнышком большинство за день стирались, хотя изредка попадались экземпляры, которые приходилось неделю держать до сплошного 0xFF.
P.S. На Роман-коше стирать не пробовал. Подозреваю, что на высоте в полтора километра за несколько часов бы все стерлись )
P.S. На Роман-коше стирать не пробовал. Подозреваю, что на высоте в полтора километра за несколько часов бы все стерлись )
Re: Stm32 с чего начать изучение...
VladislavS, ты что ты дал, там стартап какой-то скудныйне говоря уж про SystemInit(). И где само копирование? Самому ручками прописывать?
Код: Выделить всё
/*----------------------------------------------------------------------------
Reset Handler called on controller reset
*----------------------------------------------------------------------------*/
void Reset_Handler(void)
{
SystemInit(); /* CMSIS System Initialization */
__PROGRAM_START(); /* Enter PreMain (C library entry point) */
}а я то думал, но по чему из ram толком ни чего не работает.VladislavS писал(а):что при выполнении кода из RAM
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: Stm32 с чего начать изучение...
[uquote="Dimon456",url="/forum/viewtopic.php?p=4168928#p4168928"]а я то думал, но по чему из ram толком ни чего не работает.[/uquote]Вывод неверный. Копирование данных самих в себя только время лишнее занимает и ничего в работе прошивки не меняет.
-
Professor Chaos
- Открыл глаза
- Сообщения: 41
- Зарегистрирован: Вс мар 21, 2021 11:06:04
Re: Stm32 с чего начать изучение...
Видимо, внутри __PROGRAM_START(). Это ведь Enter PreMain (C library entry point). Там создаются и инициализируются начальными значениями глобальные и локальные статические данные в RAM-памяти.Dimon456 писал(а):И где само копирование? Самому ручками прописывать?
Re: Stm32 с чего начать изучение...
Здравствуйте, друзья!
Пересаживаюсь с АВР на СТМ, изучаю, вот в голову залезла бестолковая идея: сделать функцию расчёта частоты работы МК.
По сути - всё изветно: кварц, все прескалеры, но... Идея сделать расчёт универсальным, а не просто взять известные цифры и перемножить. То есть, сделать функцию расчёта по параметрам, заданым в SystemClock_Config();
Но как вытянуть численное значение из строки RCC_OscInitStruct.PLL.PLLN = 168; ?
И, в продолжение, есть параметры, который описаны так: RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;, тут вопрос как их запихнуть в IF для сравнения и последующего приравнивания некой переменной числа.
Как знаю - попробовал, не работает. Прошу помощи.
Заранее спасибо и простите мою неграмотность
Пересаживаюсь с АВР на СТМ, изучаю, вот в голову залезла бестолковая идея: сделать функцию расчёта частоты работы МК.
По сути - всё изветно: кварц, все прескалеры, но... Идея сделать расчёт универсальным, а не просто взять известные цифры и перемножить. То есть, сделать функцию расчёта по параметрам, заданым в SystemClock_Config();
Но как вытянуть численное значение из строки RCC_OscInitStruct.PLL.PLLN = 168; ?
И, в продолжение, есть параметры, который описаны так: RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;, тут вопрос как их запихнуть в IF для сравнения и последующего приравнивания некой переменной числа.
Как знаю - попробовал, не работает. Прошу помощи.
Заранее спасибо и простите мою неграмотность
Только те, кто предпринимают абсурдные попытки, смогут достичь невозможного.
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: Stm32 с чего начать изучение...
Все делители в конце концов ложатся в регистры RCC. Оттуда их можно читать. Только пустое это. Зачем вычислять то что вы сами же и задаёта?
Re: Stm32 с чего начать изучение...
Она уже есть! Найдите поиском ф-цию SystemCoreClockUpdate. Она входит в стандартную поставку и генерируется вместе с созданием проекта.делать функцию расчёта частоты работы МК.
Эта функция обновляет глобальную переменную SystemCoreClock, которая может использоваться в выражениях для задания частотозависимых интервалов. Например при настройке таймера.
Необходимость в этой функции может возникать при неявном задании частоты МК. Например, в L-серии при выходе из стоп-режимов МК может запускаться на иной частоте, чем при нормальном старте по POR.
Re: Stm32 с чего начать изучение...
[uquote="НовыйДень",url="/forum/viewtopic.php?p=4220054#p4220054"]
Эта функция обновляет глобальную переменную SystemCoreClock, которая может использоваться в выражениях для задания частотозависимых интервалов. Например при настройке таймера.
Необходимость в этой функции может возникать при неявном задании частоты МК. Например, в L-серии при выходе из стоп-режимов МК может запускаться на иной частоте, чем при нормальном старте по POR.[/uquote]Большое спаси за наводку! Действительно, там, в SystemCoreClockUpdate происходит нужный мне расчёт. Но... Если я ссылаюсь на эту переменную (sysclockfreq) в основной программе - компилятор ругается на необьявленность (делаю всё в CubeIDE). Так же и с другими переменными из этой функции. Ещё есть функция uint32_t HAL_RCC_GetHCLKFreq(void). С ней та же беда. Что-то не пойму, как заставить выполняться эти функции... Файлы прикреплены к проекту...
В рамках изучения STM32 =)
Она уже есть! Найдите поиском ф-цию SystemCoreClockUpdate. Она входит в стандартную поставку и генерируется вместе с созданием проекта.делать функцию расчёта частоты работы МК.
Эта функция обновляет глобальную переменную SystemCoreClock, которая может использоваться в выражениях для задания частотозависимых интервалов. Например при настройке таймера.
Необходимость в этой функции может возникать при неявном задании частоты МК. Например, в L-серии при выходе из стоп-режимов МК может запускаться на иной частоте, чем при нормальном старте по POR.[/uquote]Большое спаси за наводку! Действительно, там, в SystemCoreClockUpdate происходит нужный мне расчёт. Но... Если я ссылаюсь на эту переменную (sysclockfreq) в основной программе - компилятор ругается на необьявленность (делаю всё в CubeIDE). Так же и с другими переменными из этой функции. Ещё есть функция uint32_t HAL_RCC_GetHCLKFreq(void). С ней та же беда. Что-то не пойму, как заставить выполняться эти функции... Файлы прикреплены к проекту...
Всё в виде научного экспериментаVladislavS писал(а):Все делители в конце концов ложатся в регистры RCC. Оттуда их можно читать. Только пустое это. Зачем вычислять то что вы сами же и задаёта?
Только те, кто предпринимают абсурдные попытки, смогут достичь невозможного.
Re: Stm32 с чего начать изучение...
Эта переменная объявляется как extern в одноименном заголовочном файле (system_stm32.... .h) и по идее, этот файл должен быть подключен при геренации проекта в CubeIDE.
В любом случае, вы можете объявить переменную вручную через extern в нужном месте:
extern uint32_t SystemCoreClock;
В любом случае, вы можете объявить переменную вручную через extern в нужном месте:
extern uint32_t SystemCoreClock;
Re: Stm32 с чего начать изучение...
[uquote="НовыйДень",url="/forum/viewtopic.php?p=4220096#p4220096"]Эта переменная объявляется как extern в одноименном заголовочном файле (system_stm32.... .h) и по идее, этот файл должен быть подключен при геренации проекта в CubeIDE.
В любом случае, вы можете объявить переменную вручную через extern в нужном месте:
extern uint32_t SystemCoreClock;[/uquote]
Большое спасибо за советы, друзья! Что-то получилось) Ещё не понял что) Странные данные на экран вывел (31232 зайцев). Ошибку нашёл, двигаюсь дальше!
UPD: всё, вывел правильно
168 МГц =)
В любом случае, вы можете объявить переменную вручную через extern в нужном месте:
extern uint32_t SystemCoreClock;[/uquote]
Большое спасибо за советы, друзья! Что-то получилось) Ещё не понял что) Странные данные на экран вывел (31232 зайцев). Ошибку нашёл, двигаюсь дальше!
UPD: всё, вывел правильно
Только те, кто предпринимают абсурдные попытки, смогут достичь невозможного.
Re: Stm32 с чего начать изучение...
Всем привет!
4 дня впервые потратил на приобщение к F030F4P6, из-за 12-битного ADC.
Проект собираю в STM32CubeIDE 1.9.0. Исходники моего говнотворения прилагаю.
Собственно, мой вопрос. В avr-gcc я мог легко оформить кусок кода в виде:
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
...
}
а здесь (gcc-arm-none-eabi) не понятно, по хидерам искал, ничего дельного не нашел.
Как включить кусок кода в атомик-блок?
Или, какие-то другие механизмы задействуются?
И, буду рад к критическим коментариям к приложенной писанине.
main.h
main.c
4 дня впервые потратил на приобщение к F030F4P6, из-за 12-битного ADC.
Проект собираю в STM32CubeIDE 1.9.0. Исходники моего говнотворения прилагаю.
Собственно, мой вопрос. В avr-gcc я мог легко оформить кусок кода в виде:
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
...
}
а здесь (gcc-arm-none-eabi) не понятно, по хидерам искал, ничего дельного не нашел.
Как включить кусок кода в атомик-блок?
Или, какие-то другие механизмы задействуются?
И, буду рад к критическим коментариям к приложенной писанине.
main.h
Спойлер
Код: Выделить всё
#pragma once
#define DEBUG_USART1 1
#define SOME_FUNC 1
#define LED_FLASH 1
extern volatile uint32_t uwTick;
#define ChDataBits (8u)
#define ChDataSize (1u << ChDataBits)
typedef struct {
uint16_t ch0;
uint16_t ch1;
} ChData_TypeDef;
extern volatile ChData_TypeDef ChData[ChDataSize];
extern volatile uint16_t adcRawCh0, adcRawCh1;
void initRCC(void);
void initGPIO(void);
void initADC1(void);
void calADC1(void);
void stopADC1(void);
void startADC1(void* pData, uint16_t num, uint32_t ch, uint8_t stime);
#ifdef SOME_FUNC
void delayMs(uint32_t delay);
uint16_t scmADC1(uint32_t ch);
#endif
#ifdef DEBUG_USART1
extern char aText[64];
void initUSART1(void);
void postsz(char* pSz);
void sendsz(char* pSz);
void sendc(char c);
#endif
Спойлер
Код: Выделить всё
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include "stm32f0xx.h"
#include "main.h"
volatile ChData_TypeDef ChData[ChDataSize];
volatile uint16_t adcRawCh0 = 0, adcRawCh1 = 0;
// DMA1 Channel 2 and Channel 3 interrupt handler
void DMA1_Channel2_3_IRQHandler(void)
{
// A Transfer Complete or Transfer Error flag
if(READ_BIT(DMA1->ISR, DMA_ISR_TCIF2 | DMA_ISR_TEIF2) != RESET) {
// Disable DMA1 Channel2
CLEAR_BIT(DMA1_Channel2->CCR, DMA_CCR_EN);
// Channel2 clear interrupt flags
SET_BIT(DMA1->IFCR, DMA_IFCR_CGIF2 | DMA_IFCR_CTCIF2 | DMA_IFCR_CHTIF2 | DMA_IFCR_CTEIF2);
// average calc
uint32_t sch0 = 0, sch1 = 0;
ChData_TypeDef* pch = (ChData_TypeDef*)ChData;
for(uint16_t i = 0; i < (sizeof(ChData)/(sizeof(ChData[0]))); i++, pch++) {
sch0 += pch->ch0;
sch1 += pch->ch1;
}
sch0 += (sizeof(ChData)/(sizeof(ChData[0]))) >> 1;
sch1 += (sizeof(ChData)/(sizeof(ChData[0]))) >> 1;
adcRawCh0 = sch0 >> ChDataBits;
adcRawCh1 = sch1 >> ChDataBits;
}
}
int main(void)
{
initRCC();
initGPIO();
#ifdef DEBUG_USART1
initUSART1();
#endif
initADC1();
memset((void*)ChData, 0, sizeof(ChData));
#ifdef LED_FLASH
SET_BIT(GPIOB->BSRR, GPIO_BSRR_BS_1);
#endif
#ifdef DEBUG_USART1
postsz("\r\nStart!\r\n\r\n");
#endif
uint32_t uwAdcMs = uwTick;
uint32_t uwCalcMs = uwTick;
#ifdef LED_FLASH
uint32_t uwLedMs = uwTick;
#endif
while(1) {
if(uwTick - uwAdcMs >= 100u) { // every 100 msec
uwAdcMs = uwTick;
startADC1((void*)ChData,
(sizeof(ChData)/(sizeof(ChData[0])) << 1),
ADC_CHSELR_CHSEL1 | ADC_CHSELR_CHSEL0,
ADC_SMPR_SMP_2 | ADC_SMPR_SMP_1); // tCONV = 6 usec
}
if(uwTick - uwCalcMs >= 500u) { // every 500 msec
uwCalcMs = uwTick;
sprintf(aText, "%u\t%u\r\n", adcRawCh0, adcRawCh1);
postsz(aText);
}
#ifdef LED_FLASH
if(uwTick - uwLedMs >= 500u) { // every 500 msec
uwLedMs = uwTick;
SET_BIT(GPIOB->BSRR, READ_BIT(GPIOB->IDR, GPIO_IDR_1) ? GPIO_BSRR_BR_1 : GPIO_BSRR_BS_1);
}
#endif
}
}
// GPIO initialization
void initGPIO(void)
{
// I/O port A, B, F clock enable
SET_BIT(RCC->AHBENR, RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOFEN);
// ADC1: PORTA0 (NTC0), PORTA1 (NTC1) Analog mode
SET_BIT(GPIOA->MODER, GPIO_MODER_MODER0 | GPIO_MODER_MODER1);
#ifdef LED_FLASH
// PORTB1: General purpose output mode (LED)
MODIFY_REG(GPIOB->MODER, GPIO_MODER_MODER1, GPIO_MODER_MODER1_0);
// PORTB1: push-pull
CLEAR_BIT(GPIOB->OTYPER, GPIO_OTYPER_OT_1);
// PORTB1: 2 MHz
CLEAR_BIT(GPIOB->OSPEEDR, GPIO_OSPEEDR_OSPEEDR1);
// PORTB1: No pull-up or pull-down
CLEAR_BIT(GPIOB->PUPDR, GPIO_PUPDR_PUPDR1);
#endif
#ifdef DEBUG_USART1
// USART1: PORTA9 (Tx), PORTA10 (Rx): Alternate function mode
MODIFY_REG(GPIOA->MODER, GPIO_MODER_MODER9 | GPIO_MODER_MODER10, GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1);
// PORTA9 (Tx), PORTA10 (Rx): Output push-pull
CLEAR_BIT(GPIOA->OTYPER, GPIO_OTYPER_OT_9 | GPIO_OTYPER_OT_10);
// PORTA9 (Tx), PORTA10 (Rx): 50 MHz
SET_BIT(GPIOA->OSPEEDR, GPIO_OSPEEDR_OSPEEDR9_0 | GPIO_OSPEEDR_OSPEEDR9_1 | GPIO_OSPEEDR_OSPEEDR10_0 | GPIO_OSPEEDR_OSPEEDR10_1);
// PORTA9 (Tx): No pull-up or pull-down, PORTA10 (Rx): Pull-up
MODIFY_REG(GPIOA->PUPDR, GPIO_PUPDR_PUPDR9 | GPIO_PUPDR_PUPDR10, GPIO_PUPDR_PUPDR10_0);
// PORTA9 (Tx), PORTA10 (Rx): Alternate function AF1
MODIFY_REG(GPIOA->AFR[1], GPIO_AFRH_AFSEL9 | GPIO_AFRH_AFSEL10, (1UL << GPIO_AFRH_AFSEL9_Pos) | (1UL << GPIO_AFRH_AFSEL10_Pos));
#endif
}
// ADC stop
void stopADC1(void)
{
// ADC group regular conversion stop
if(READ_BIT(ADC1->CR, ADC_CR_ADSTART) != RESET) {
SET_BIT(ADC1->CR, ADC_CR_ADSTP);
// wait for ADC group regular conversion stop
while(READ_BIT(ADC1->CR, ADC_CR_ADSTP) != RESET);
}
}
// ADC start
void startADC1(void* pData, uint16_t num, uint32_t ch, uint8_t stime)
{
// ADC stop
stopADC1();
// Sampling time selection, Fadc = 14 MHz
// SMP Sampling tCONV,
// time,ADCcycles usec
// 000 1,5 1,00
// 001 7,5 1,43
// 010 13,5 1,86
// 011 28,5 2,93
// 100 41,5 3,86
// 101 55,5 4,86
// 110 71,5 6,00
// 111 239,5 18,00
MODIFY_REG(ADC1->SMPR, ADC_SMPR_SMP, stime);
// ADC channel selection
MODIFY_REG(ADC1->CHSELR, ADC_CHSELR_CHSEL, ch);
// Analog watchdog disabled, ADC group regular sequencer discontinuous mode disabled,
// ADC low power auto power off disabled, Wait conversion mode off,
// DR register is preserved with the old data when an overrun is detected,
// Hardware trigger detection disabled, Right alignment, Data resolution 12 bits,
// Scan sequence direction Upward, DMA one shot mode selected,
// Continuous conversion mode enabled, DMA enabled
MODIFY_REG(ADC1->CFGR1, ADC_CFGR1_AWD1EN | ADC_CFGR1_DISCEN | ADC_CFGR1_AUTOFF | ADC_CFGR1_WAIT |
ADC_CFGR1_OVRMOD | ADC_CFGR1_EXTEN | ADC_CFGR1_ALIGN | ADC_CFGR1_RES | ADC_CFGR1_SCANDIR | ADC_CFGR1_DMACFG,
ADC_CFGR1_CONT | ADC_CFGR1_DMAEN);
// DMA
// wait DMA1 Channel2 Transfer Complete flag
if(READ_BIT(DMA1_Channel2->CCR, DMA_CCR_EN) != RESET)
// wait for Transfer Complete or Transfer Error flag
while(READ_BIT(DMA1->ISR, DMA_ISR_TCIF2 | DMA_ISR_TEIF2) == RESET);
// Disable DMA1 Channel2
CLEAR_BIT(DMA1_Channel2->CCR, DMA_CCR_EN);
// ADC DMA remap to DMA1 Chanel2
SET_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_ADC_DMA_RMP);
// Configure the peripheral address register
WRITE_REG(DMA1_Channel2->CPAR, (uint32_t)&(ADC1->DR));
// Configure the memory address
WRITE_REG(DMA1_Channel2->CMAR, (uint32_t)pData);
// Configure the number of DMA tranfer to be performs on channel
MODIFY_REG(DMA1_Channel2->CNDTR, 0xffffu, num);
// Channel priority level 01 Medium, Peripheral & Memory size 01 16-bits,
// Memory increment mode 1 enabled, Data transfer direction 0 Read from peripheral
// Circular mode disabled, Transfer complete interrupt enabled
MODIFY_REG(DMA1_Channel2->CCR, DMA_CCR_MEM2MEM | DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE |
DMA_CCR_PINC | DMA_CCR_CIRC | DMA_CCR_DIR | DMA_CCR_TEIE | DMA_CCR_HTIE | DMA_CCR_EN,
DMA_CCR_PL_0 | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0 | DMA_CCR_MINC | DMA_CCR_TCIE);
// ADC group regular conversion start
SET_BIT(ADC1->CR, ADC_CR_ADSTART);
// Enable DMA1 Channel2
SET_BIT(DMA1_Channel2->CCR, DMA_CCR_EN);
// DMA1 Channel2 (ADC) and Channel3 interrupt enable
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
NVIC_SetPriority(DMA1_Channel2_3_IRQn, 2);
}
// ADC calibration
void calADC1(void)
{
// ADC disable
if(READ_BIT(ADC1->CR, ADC_CR_ADEN) != RESET) {
// ADC stop
stopADC1();
// ADC disable
SET_BIT(ADC1->CR, ADC_CR_ADDIS);
// wait for ADC1 disable
while(READ_BIT(ADC1->CR, ADC_CR_ADEN) != RESET);
}
// ADC DMA transfer disable
CLEAR_BIT(ADC1->CFGR1, ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG);
// ADC calibration
SET_BIT(ADC1->CR, ADC_CR_ADCAL);
// Wait until ADCAL=0
while(READ_BIT(ADC1->CR, ADC_CR_ADCAL) != RESET);
// ADC Enable
// Clear the ADRDY bit
if(READ_BIT(ADC1->ISR, ADC_ISR_ADRDY) != RESET)
SET_BIT(ADC1->ISR, ADC_ISR_ADRDY);
// ADC enable
SET_BIT(ADC1->CR, ADC_CR_ADEN);
// wait for ADC ready flag
while(READ_BIT(ADC1->ISR, ADC_ISR_ADRDY) == RESET);
}
// ADC initialization
void initADC1(void)
{
// HSI14 clock request from ADC disable
SET_BIT(RCC->CR2, RCC_CR2_HSI14DIS);
// Internal High Speed 14MHz clock enable
SET_BIT(RCC->CR2, RCC_CR2_HSI14ON);
// wait for Internal High Speed 14MHz clock ready
while(READ_BIT(RCC->CR2, RCC_CR2_HSI14RDY) == RESET);
// Internal High Speed 14MHz clock enable
CLEAR_BIT(RCC->CR2, RCC_CR2_HSI14DIS);
// ADCCLK (Asynchronous clock mode), generated at product level (refer to RCC section)
CLEAR_BIT(ADC1->CFGR2, RCC_CFGR2_PREDIV);
// ADC1 clock enable
SET_BIT(RCC->APB2ENR, RCC_APB2ENR_ADCEN);
// ADC calibration
calADC1();
}
volatile uint32_t uwTick = 0;
// SysTick interrupt handler
void SysTick_Handler(void)
{
uwTick++;
}
// RCC initialization
void initRCC(void)
{
// SYSCFG and comparator clock enable
SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGCOMPEN);
// Flash Latency: One wait state, if 24 MHz < SYSCLK ≤ 48 MHz
SET_BIT(FLASH->ACR, FLASH_ACR_LATENCY);
// Enable the Internal High Speed oscillator (HSI)
SET_BIT(RCC->CR, RCC_CR_HSION);
while(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RESET);
// Disable the main PLL
CLEAR_BIT(RCC->CR, RCC_CR_PLLON);
while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != RESET);
// PLL HSI /2 x12
MODIFY_REG(RCC->CFGR, RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL, RCC_CFGR_PLLSRC_HSI_DIV2|RCC_CFGR_PLLMUL12);
MODIFY_REG(RCC->CFGR2, RCC_CFGR2_PREDIV, RCC_CFGR2_PREDIV_DIV1);
// Enable the PLL
SET_BIT(RCC->CR, RCC_CR_PLLON);
while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET);
// HCLK and PCLK: no prescaler, System clock: PLL 48 MHz
MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE | RCC_CFGR_PPRE | RCC_CFGR_SW, RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE_DIV1 | RCC_CFGR_SW_PLL);
// PLL used as system clock
while(READ_BIT(RCC->CFGR, RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
// set system variable SystemCoreClock to current clock value
SystemCoreClockUpdate();
// set SysTick timer to 1 ms delay
SysTick_Config(SystemCoreClock / 1000);
// DMA1 clock enable
SET_BIT(RCC->AHBENR, RCC_AHBENR_DMAEN);
}
#ifdef SOME_FUNC
// set delay in miliseconds using sysTick timer
void delayMs(uint32_t delay)
{
uint32_t uwT0 = uwTick;
while(uwTick - uwT0 < delay);
}
uint16_t scmADC1(uint32_t ch)
{
// ADC stop
stopADC1();
// Sampling time selection
MODIFY_REG(ADC1->SMPR, ADC_SMPR_SMP, ADC_SMPR_SMP_2);
// Analog watchdog disabled, ADC group regular sequencer discontinuous mode disabled,
// ADC low power auto power off disabled, Wait conversion mode off,
// Continuous conversion mode disabled, DR register is preserved with the old data when an overrun is detected,
// Hardware trigger detection disabled, Right alignment, Data resolution 12 bits,
// Scan sequence direction Upward, DMA one shot mode selected, DMA disabled
CLEAR_BIT(ADC1->CFGR1, ADC_CFGR1_AWD1EN | ADC_CFGR1_DISCEN | ADC_CFGR1_AUTOFF | ADC_CFGR1_WAIT |
ADC_CFGR1_CONT | ADC_CFGR1_OVRMOD | ADC_CFGR1_EXTEN | ADC_CFGR1_ALIGN | ADC_CFGR1_RES |
ADC_CFGR1_SCANDIR | ADC_CFGR1_DMACFG | ADC_CFGR1_DMAEN);
// ADC channel selection
MODIFY_REG(ADC1->CHSELR, ADC_CHSELR_CHSEL, ch);
// ADC group regular conversion start
SET_BIT(ADC1->CR, ADC_CR_ADSTART);
// ADC group regular end of unitary conversion flag
while(READ_BIT(ADC1->ISR, ADC_ISR_EOC) == RESET);
// ADC data register
return (uint16_t)(READ_REG(ADC1->DR) & 0xffffu);
}
#endif
#ifdef DEBUG_USART1
char aText[64];
// USART initialization
void initUSART1(void)
{
// System clock (SYSCLK) selected as USART1 clock
MODIFY_REG(RCC->CFGR3, RCC_CFGR3_USART1SW, RCC_CFGR3_USART1SW_SYSCLK);
// USART1 clock enable
SET_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN);
// USART1: Baud rate 115200 for standard USART (oversampling by 16, OVER8 = 0)
MODIFY_REG(USART1->BRR, 0xffffu, 417u);
// USART1: DMA Enable Transmitter
SET_BIT(USART1->CR3, USART_CR3_DMAT);
// USART1: 1 stop bit, CK pin disabled,
// USART1->CR2 = 0;
// USART1: 1 Start bit, 8 data bits, Parity control disabled, Oversampling by 16,
// Transmitter Enable, Receiver Enable, USART1 Enable | USART_CR1_RE
SET_BIT(USART1->CR1, USART_CR1_TE | USART_CR1_UE);
}
void postsz(char* pSz)
{
// wait DMA1 Channel4 Transfer Complete flag
if(READ_BIT(DMA1_Channel4->CCR, DMA_CCR_EN))
// wait for Transfer Complete or Transfer Error flag
while(READ_BIT(DMA1->ISR, DMA_ISR_TCIF4 | DMA_ISR_TEIF4) == RESET);
// Disable DMA1 Channel4
CLEAR_BIT(DMA1_Channel4->CCR, DMA_CCR_EN);
// Remap (USART1_TX DMA request mapped on DMA channel 4)
SET_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_USART1TX_DMA_RMP);
// Configure the peripheral address register
WRITE_REG(DMA1_Channel4->CPAR, (uint32_t)&(USART1->TDR));
// Configure the memory address
WRITE_REG(DMA1_Channel4->CMAR, (uint32_t)pSz);
// Configure the number of DMA tranfer to be performs on channel
WRITE_REG(DMA1_Channel4->CNDTR, strlen(pSz));
// Channel priority level 00 Low, Peripheral & Memory size 00 8-bits,
// Memory increment mode 1 enabled, Data transfer direction 1: Read from memory
MODIFY_REG(DMA1_Channel4->CCR, DMA_CCR_MEM2MEM | DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE |
DMA_CCR_PINC | DMA_CCR_CIRC | DMA_CCR_TEIE | DMA_CCR_HTIE | DMA_CCR_TCIE | DMA_CCR_EN,
DMA_CCR_MINC | DMA_CCR_DIR);
// Enable DMA1 Channel4
SET_BIT(DMA1_Channel4->CCR, DMA_CCR_EN);
}
void sendsz(char* pSz)
{
if(pSz)
while(*pSz)
sendc(*pSz++);
}
void sendc(char c)
{
// wait
if(READ_BIT(DMA1_Channel4->CCR, DMA_CCR_EN))
// wait DMA1 Channel4 Transfer Complete flag
while(READ_BIT(DMA1->ISR, DMA_ISR_TCIF4 | DMA_ISR_TEIF4) == RESET);
else
// Wait Transmit Data Register Empty
while(READ_BIT(USART1->ISR, USART_ISR_TXE) == RESET);
USART1->TDR = c;
}
#endif
- Вложения
-
- STM32F030 clean USART DMA ADC.rar
- (81.56 КБ) 104 скачивания
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: Stm32 с чего начать изучение...
[uquote="Карбофос",url="/forum/viewtopic.php?p=4225283#p4225283"]Как включить кусок кода в атомик-блок?[/uquote]Вариантов много. Самое простое
Код: Выделить всё
uint32_t tmp = __get_PRIMASK();
__disable_irq();
// код
__set_PRIMASK(tmp);
Re: Stm32 с чего начать изучение...
Вот это портянка... Вы лучше на словах скажите, куда хотите впендюрить атомарность и почему, соппсна, оная вам нужна для АЦП?
Атомарность - она для чего нужна: если в обработчике прерывания вы обращаетесь к тому же ресурсу, что и и в общем коде. Или при работе с RTOS. Но RTOS предоставляет свои алгоритмы защиты. Без RTOS можно временно отключить вектор прерывания (через функции NVIC), в котором происходит параллельное действие. Или временно полностью запертить прерывания.
Атомарность - она для чего нужна: если в обработчике прерывания вы обращаетесь к тому же ресурсу, что и и в общем коде. Или при работе с RTOS. Но RTOS предоставляет свои алгоритмы защиты. Без RTOS можно временно отключить вектор прерывания (через функции NVIC), в котором происходит параллельное действие. Или временно полностью запертить прерывания.


