Рейтинг
28.46
голосов: 30

О блоге

Работа с ядром CortexM3 и периферией STM

Администраторы (1)

Модераторы (0)

Модераторов здесь не замечено

Читатели (263)

ploop _YS_ m3hc Krieger Tabke marvin_yorke Ultrin WildCat hexanaft Vga Alatar mzw Reverb grand1987 dievgen woogle PahanMenski anper citizen ZiB

Все читатели блога

Изучение STM32. Уроки по программированию STM32F4 Discovery.

На просторах РУНЕТа можно много найти инфы по изучению STM32, оформленные в виде статей, уроков, видео уроков. Подавляющее большинство материала на эту тему написано на SPL или чистом CMSIS. Но компания ST довольно упорно продвигает в массы библиотеку HAL и его генератор STM32CubeMX. Данная библиотека уже многим пришлась по вкусу. Так как я программист гуру не от бога, то при переходе от 8-ми битных мк на STM32 использование данной библиотеки показалось мне довольно правильным решением.

Читать дальше
  • +1
  • 05 декабря 2015, 09:23
  • Helix

Stm32F0 и 1-wire

Сегодня решил попробовать работу связки STM32F030 и DS18B20 как описал steel_ne здесь. Не получилось определить наличие датчика на OWI по сбросу так, как мне хотелось. Код steel_ne полностью рабочий, за исключением возврата значения функцией OW_Reset при закороченной линии данных. Проблемное место нашел и исправил.


Читать дальше

Опыт использования USART3 в STM32F100C6

Как известно виновники многих открытий — случайности.
Так и я не обратил внимания, что у STM32F100C6 по документации всего два USART и развел третий. Запустил обмен на передачу, все замечательно работало. Однако когда начал налаживать прерывание на прием обнаружил, что в STM32F10x_StdPeriph_Driver для этого МК прерывание не настраивается. Что такое думаю, как так. Открыл даташит и смотрю, а их два.
Ну думаю раз на передачу работает дело за тем, что бы допилить STM32F10x_StdPeriph_Driver.
Выполнил следующие доработки (компилятор KEIL)
В файле stm32f10x.h в разделе #ifdef STM32F10X_LD_VL добавил строку
USART3_IRQn = 39, /*!< USART3 global Interrupt */
которую скопировал из раздела
#ifdef STM32F10X_MD

Далее в фале запуска startup_stm32f10x_ld_vl.s
добавил обработчик прерывания от USART3
Прием заработал.
Оба отредактированных файла прилагаю.

На передачу USART3 работал долго и уверено, а вот когда наладил прерывание через некоторое время, после активного обмена МК перестал работать. Прошивается, но не работает. Под отладчиком посмотреть, что там происходит, возможности нет из-за особенности схемы.

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

Демоны в АЦП STM32



Современные АЦП обычно содержат внутри УВХ. В последнее время АЦП часто строятся по схеме уравновешивания заряда, а не уравновешивания токов, как это было в АЦП на основе резисторной матрицы R-2R. В случае АЦП с уравновешиванием заряда роль емкости УВХ выполняет внутренняя матрица конденсаторов. Конденсаторы матрицы в процессе преобразования перезаряжаются. Поэтому вход такого АЦП ведет себя достаточно нетривиально. Именно к такому типу АЦП относится и внутренний АЦП микроконтроллеров STM32. Довольно много информации по этому поводу содержится в документе AN2834. Но там полезные рекомендации, как на стр. 37: «Do not add any external capacitor (Cext) to the input pin when applying this above workaround» чередуются с вредными советами, как на стр. 39: «An extra large Cext enables sampling more often». Это подтолкнуло к написанию данного поста.



Читать дальше...

Управление светодиодной лентой на WS2812B с STM32F10x

Про подключение светодиодных лент на WS2812B к STM32 написано немало статей. Наиболее правильный вариант, с моей точки зрения, описан в статье на Хабре, однако у него есть ряд недостатков:

  • Новичку трудно в нем разобраться
  • Неэкономно расходуется память, что позволено STM32F4 — не позволено STM32F10x

Оба этих недостатка я попытался устранить в своей библиотеке stm32f10x-ws2812b-lib.


Читать дальше

2-x фазный ШИМ (PWM) генератор на STM32F030F4

Для питания ряда устройств (например электродвигателей переменного тока) иногда необходимо наличие сдвинутых по фазе питающих напряжений. Для питания 2-х фазных индукционных двигателей необходимо наличие двух фаз синусоидального напряжения с частотой 400 Герц и сдвинутых по фазе на 90 градусов. Один из примеров таких двигателей являются двигатели серии ДИД. Они интересны тем, что их частота вращения может составлять от 16000 до 18000 об/мин. Для питания таких двигателей и было сделано данное устройство, которое представляет собой задающий генератор 2-х фазного 400 Гц напряжений сдвинутых по фазе на 90 градусов относительно друг друга.
В качестве микроконтроллера использован STM32F030F4. Его выбор обусловлен его «минимализмом» — наименьший из корпусов в серии STM32F0 и естественно с минимальной стоимостью. Схема подключения изображена ниже. Микроконтроллер работает на частоте 48 МГц. В качестве задающего генератора использован TIM3, так как в данном контроллере только этот таймер можно конфигурировать так, чтобы использовать выходы трех каналов. Третий канал можно в случае необходимости использовать для генерации 3-фазного напряжения. Таймер работает в режиме генерации ШИМ (PWM). Для получения синусоидального напряжения 400 Гц в канале используется высокочастотное изменение коэффициента ШИМ с частотой 40 кГц, на которую настроен системный таймер SysTick. Синусоида формируется с помощью таблицы значений синуса с шагом 360/100 градусов. Очень полезный калькулятор для такого рода таблиц можно найти на сайте. При желании с помощью АЦП можно управлять амплитудой, фазой, частотой генерации. Но в данной реализации это не сделано.



Ниже показаны выходные осциллограммы генератора. Синяя и фиолетовая синусоиды — сдвинуты на 90 градусов, желтая — выход таймера для синей синусоиды, зеленый — тестовый сигнал генерируемый при начале формирования синусоиды




Читать дальше

Удобная настройка GPIO STM32F030. Мой велосипед.

Долгое время я настраивал порты различных микроконтроллеров STM32 при помощи Standart Peripheral Library.


Читать дальше

Атомарный доступ к битам регистров bit-band через макрос

Не буду расписывать, зачем нужен этот самый атомарный доступ. Будем считать, что если он Вам понадобился, значит надо.
Дело было так. Когда этот самый атомарный доступ понадобился мне, вспомнилось про наличие bit-band региона памяти в STM32. В даташите на Cortex M3 есть формула, по ней можно всё рассчитать, есть рисунки, в общем всё ясно и понятно. Однако хотелось некой автоматизации. Поискал. Нашел ARMовскую infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4203.html рекомендацию по применению. Уже лучше. Но тут заглянул в хедеры CMSIS и понял, что ARMовские макросы можно «допилить»…


Читать дальше

Configuration Wizard в KEIL. Продолжение на примере настройки USART, ADC для STM32F4xx

Итак, продолжаем настраивать периферию с помощью Configuration Wizard. Возможно в будущем появятся еще экземпляры по разным устройствам, и в итоге объединим все в один мегапроект. Ну это так, помечталось мне.
Начнем:

Читать дальше

измеряем частоту аппаратно

Была задача измерять частоту а потом усреднять результат.
реализация на прерываниях не понравилась — сделал чисто аппаратно + дма
суть такая первый таймер отмеряет нужное время( по захвату), и дергает ДМА, ДМА забирает текущее значение и складывает в память, по переполнения счетчика ( следующий за захватом такт) происходит сброс счетчика импульсов (реализация stm32f100) но перенести на другие — не проблема, главное разобраться кто какой дма дергает)
вот рабочий код. делает 256 отсчетов и складывает в память, и так по кругу. процессор не задействовано
по завершению одного прохода ДМА, взводится флаг — данные готовы и уже можно что то считать. Прерывание ДМА дергается только один раз

//размер циклического буфера
#define FREQ_BUF_SIZE 256
//тут будут лежать частоты

unsigned short FREQ_BUF[FREQ_BUF_SIZE];

// данные уже готовы
void DMA1_Channel5_IRQHandler ( void)
{
	DMA1->IFCR |=DMA_IFCR_CGIF5;
        DMA1_Channel5->CCR &= ~DMA_CCR5_TCIE; //заблокируем повторное использование прерывания от  дма
	ValidData=1;
}

void Init()
{
//счетные таймера

TIM15->PSC=   8000-1;			//пред делитель
TIM15->ARR=   10001 ;		    //считаем до....
TIM15->CR2=   TIM_CR2_MMS_1;	//TRGO дергаем по перезагрузке таймера - для ресета счетчика 2
//TIM15->SMCR=   TIM_SMCR_MSM;
TIM15->DIER=  TIM_DIER_CC1DE;   // запрос ДМА по каналу сравнения 1
TIM15->DIER |=  TIM_DIER_CC2IE; //прерывание
TIM15->CCMR1= TIM_CCMR1_OC1M_0; //TIMx_CNT==TIMx_CCR) OCxREF =1
TIM15->CR1 =  TIM_CR1_ARPE;	
TIM15->CCR1=  1000; //кода формируем запрос ДМА
TIM15->DIER |= TIM_DIER_UIE;  //прерывание по переполнению

//таймер 2 - измеритель частоты
TIM2->ARR = 0xffff;              // макс. значение до которого считаем																 //потом прерывание по переполнению
TIM2->PSC =0 ;                // пред делитель 
TIM2->CR1 =  TIM_CR1_ARPE;
TIM2->SMCR |=TIM_SMCR_TS_0;    //в режиме ведомого от таймера 15 ITR1 (TS = 001)
TIM2->SMCR |=TIM_SMCR_SMS_2;  // режим 100:  “Reset”
TIM2->SMCR |= TIM_SMCR_ECE;   // Включить режим внешнего тактирования 
TIM2->SMCR |=TIM_SMCR_ETPS_1; //входную частоту делим на 4(это для моего проекта)

//настроим ДМА  для канала  5 таймера 15 
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
DMA1_Channel5->CMAR = (uint32_t) FREQ;       //адрес буфера приемника
//Определяемся с устройствами, которые будут подключены к каналам 2 и 3:
DMA1_Channel5->CPAR = (uint32_t) &TIM2->CNT;      //адрес регистра данных передатчика 
//Задаем количество данных для обмена:
DMA1_Channel5->CNDTR = FREQ_BUF_SIZE;            //размер буфера
DMA1_Channel5->CCR = DMA_CCR5_MINC;                //запись в память, инкремент указателя в памяти
DMA1_Channel5->CCR |= DMA_CCR5_TCIE;               //канал 5
DMA1_Channel5->CCR|= DMA_CCR5_CIRC;//циклически
DMA1_Channel5->CCR|= DMA_CCR5_MSIZE_0;
DMA1_Channel5->CCR|= DMA_CCR5_PSIZE_0; //по 16 бит
DMA1_Channel5->CCR|= DMA_CCR5_TCIE; //прерывание по завершению
DMA1_Channel5->CCR |= DMA_CCR5_EN; //разрешим работу
TIM15->CR1 |= TIM_CR1_CEN ;
TIM2->CR1 |=TIM_CR1_CEN;
NVIC_EnableIRQ (DMA1_Channel5_IRQn);  
}

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