Проблема в том, что при активации прерывания по таймеру, контроллер начинает глючить. Это проявляется в таких вещах:
1) прошивка контроллера (по SWD) виснет на этапе заливки. При этом вроде как виснет само ядро и не отвисает после прекращения прошивки. Если повторно начать шить, то всё проходит успешно.
2) перестаёт работать само прерывание от таймера. Точнее работоспособность его зависит от фазы луны. Например, оно может не работать, непосредственно после пеерепрошивки, но если переподцепить питание контроллера, то оно начинает работать. Или стабильно не работает, если добавить несколько строчек кода. При том сам счётчик считает.
При этом если как либо предотвратить вызов прерывания, то этот глюк пропадает (запретить перерывание в DIER или NVIC или же не сбрасывать его регистр SR в самом прерывании, но при этом оно вызывается только один раз). Так и не смог разобраться в чём дело. Под спойлером мой код.
Спойлер
Код: Выделить всё
/*
======================
Name : main.c
Author :
Version :
Copyright : Your copyright notice
Description : Hello World in C
======================
*/
#include <stm32f0xx.h>
#include "system.h"
int main(void)
{
initialize(); // Инициализация
while(1)
{
lightStreth=(30<<8);
for(int r=0; r<1000000; r++);
//lightStreth=(50<<8); // Если разкомментировать, не работает прерывание
//for(int r=0; r<1000000; r++);
};
return 0;
}
Код: Выделить всё
/*
* system.c
*
* Created on: 04 июля 2015 г.
* Author: ifor
*/
#ifndef SYSTEM_H
#define SYSTEM_H
#include <stm32f0xx.h>
#include <stdint.h>
uint16_t lightStreth = 0;
void initialize()
{ // Инициализация системы
__enable_irq();
NVIC_EnableIRQ(TIM14_IRQn); // Размаскировываем прерывание TIM14
// Включение тактирование переферии
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN;
RCC->APB1ENR |= RCC_APB1ENR_TIM14EN;
// Настройка тактирования от внутреннего генератора на 48 МГц
// Проверяем, не включени ли у нас умножитель (PLL)?
if (RCC->CR & RCC_CR_PLLON)
{ // Переключаемся на подачу тактирования в обход PLL и выключаем его
RCC->CFGR &= ~RCC_CFGR_SW;
while ((RCC->CFGR & RCC_CFGR_SWS) ^ RCC_CFGR_SWS_HSI); // Ждём переключения
RCC->CR &= ~RCC_CR_PLLON;
}
RCC->CFGR = RCC_CFGR_PLLSRC_HSI_Div2 | RCC_CFGR_PLLMULL12 | RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE_DIV1;
// Пытаемся включить умножитель частоты на 16
RCC->CR |= RCC_CR_PLLON;
while (!(RCC->CR & RCC_CR_PLLRDY)); // Ждём устойчивого состояния умножителя
// Переключаем тактирование от умножителя
RCC->CFGR |= RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS) ^ RCC_CFGR_SWS_PLL); // Ожидание переключения на умножитель
// ---------- С этого момента частота тактирования 48 МГц ----------
// Настройка GPIO
// Сброс выходов
GPIOB->ODR = 0;
// Подсветка экрана, TIM14
GPIOB->MODER = GPIO_MODER_MODER1_1; // Альтернативный функционал
GPIOB->OSPEEDR = GPIO_OSPEEDER_OSPEEDR1;
GPIOB->AFR[0] = 0; // Переключаем вывод на выход CH1 TIM14
// Настрока TIM14 на ШИМ
//RCC->APB1RSTR |= RCC_APB1RSTR_TIM14RST;
//RCC->APB1RSTR &= ~RCC_APB1RSTR_TIM14RST;
TIM14->CR1 = TIM_CR1_ARPE; // Включаем буфферизацию ARR
TIM14->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; // Выбираем 1-й режим ШИМ
TIM14->EGR = TIM_EGR_UG; // Включаем генерацию события по обновлению
TIM14->CCER = TIM_CCER_CC1E; // Направление счёта
TIM14->ARR = 0xFFFF; // Определяем частоту ШИМ
TIM14->CCR1 = 0x0000;
TIM14->CNT = 0;
TIM14->PSC = 11;
TIM14->DIER = TIM_DIER_UIE; // Прерывание по обновлению
TIM14->CR1 |= TIM_CR1_CEN;
//TIM14->SR &= ~(TIM_SR_UIF | TIM_SR_CC1IF);
}
void setLight(uint16_t value)
{ // Установить яркость. 1 байт после запятой. От 0 до 100
const uint16_t table[102] =
{
0, 383, 770, 1162, 1557, 1955, 2358, 2765, 3177, 3592, 4011, 4435, 4863, 5295,
5731, 6172, 6618, 7067, 7522, 7981, 8444, 8912, 9385, 9863, 10345, 10833, 11325,
11822, 12324, 12831, 13344, 13861, 14384, 14911, 15445, 15983, 16527, 17077,
17631, 18192, 18758, 19330, 19908, 20491, 21080, 21675, 22276, 22884, 23497,
24116, 24742, 25374, 26012, 26657, 27308, 27966, 28631, 29302, 29979, 30664,
31355, 32054, 32759, 33472, 34192, 34919, 35653, 36394, 37144, 37900, 38664,
39436, 40216, 41003, 41799, 42602, 43414, 44233, 45061, 45897, 46742, 47595,
48457, 49327, 50206, 51094, 51991, 52897, 53811, 54736, 55669, 56612, 57564,
58526, 59497, 60479, 61470, 62471, 63482, 64503, 65535
}; // Экспонентациальная таблица
if (value > (100<<8)) value = (100<<8);
if (value == (100<<8)) TIM14->CCR1 = 0xFFFF;
uint16_t k = (value&0x00FF);
uint16_t c = (value>>8);
TIM14->CCR1 = (((uint32_t)table[c]*(0xFF-k) + (uint32_t)table[c+1]*k) >> 8);
}
void TIM14_IRQHandler()
{
// Вводим инерционность
const int k = 5;
static uint32_t o = 0;
static uint32_t i = 0;
static uint32_t i1 = 0;
i = lightStreth;
o = (((0xFF-2*k)*o + k*(i+i1))>>8);
i1 = i;
setLight(o);
TIM14->SR &= ~TIM_SR_UIF;
}
#endif
