четверг, 1 марта 2012 г.

I & STM32 discovery part10 - main timers

В предыдущей статье рассматривалась работа базовых таймеров. Теперь же мы модифицируем программу для работу в качестве таймера и контроллера диодов мы выберем один из основных таймеров.



в мк stm32f100rb 6 основных таймеров. Они немного различаются количеством выводов и функционалом, поэтому под каждую конкретную задачу программист вправе выбрать ему нужный и более подходящий таймер.
Функционал основных таймеров на несколько порядков выше чем базовых, к возможностям базовых добавлено следующее:
  • 4 независимых канала для:
    • Захвата сигнала
    • Сравнения выхода
    • Генерации ШИМ (выровненного по границе или центру)
    • Генерации одиночных импульсов
  • Схема синхронизации для контроля таймера с помощью внешних сигналов и соединения с другими таймерами.
  • Прерывания/НДП для различных событий:
    • Обновление: переполнение счетчика или его инициализация (программно или внутренними/внешними триггерами)
    • Триггеры: старт/стоп счетчика, инициализация или счет по внутреннему/внешнему триггеру.
    • Захват сигнала
    • Сравнение выхода
  • Поддержка инкрементальных(квадратурных) энкодеров и датчиков Холла
  • Входной триггер для внешнего тактового сигнала или  установки текущего положения
 Вот список возможностей обычного таймера(а точнее таймеров с 2 по 5). На основе всего этого функционала мы попробуем сделать аналог предыдущей программы с небольшими доработками. В качестве основного таймера выберем таймер за номером 3.

Как обычно начинаем с создания проекта:

nis@jane ~/stm32/examples $ cp -a 04-tim6/ 05-tim3
nis@jane ~/stm32/examples $ cd 05-tim3/

Начнем с инициализации периферии, а точнее блока ввода-вывода и таймера.
Т.к. пины выводов у нас управляются таймером то мы переключим их на альтернативные функции:

/* setup i/o port c */
LED_PORT->CRH &= ~(GPIO_CRH_CNF8 | GPIO_CRH_CNF9);
LED_PORT->CRH |= GPIO_CRH_CNF8_1 | GPIO_CRH_CNF9_1;
LED_PORT->CRH |= GPIO_CRH_MODE8_0 | GPIO_CRH_MODE9_0;


Также необходимо настроить ремап функций таймера, т.к. по умолчанию его выводы настроены на другие порты

/* remap TIM3 to pc6..9 pins port C */
AFIO->MAPR |= AFIO_MAPR_TIM3_REMAP_FULLREMAP;

С таймером же посложнее. Тут надо заменить базовую инициализацию с TIM6 на TIM3 и добавить необходимые опции. Настроим счетчик на те же параметры что и в предыдущем проекте:

/* setup TIM3 counter */
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
TIM4->PSC = 8000 - 1;
TIM4->ARR = 1000;


Далее следует настроить блок захвата - сравнения для 3го и 4го канала.
Режим работы - сравнение, выводы настроены на переключение по сравнению:

/* setup TIM3 compare block */
/** setup CC3..4 as output */
TIM3->CCMR2 &= ~(TIM_CCMR2_CC3S | TIM_CCMR2_CC4S);
/** setup CC1..2 to togle if compare */
TIM3->CCMR2 |= TIM_CCMR2_OC3M_0 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC4M_0 | TIM_CCMR2_OC4M_1;
/** setup value to compare registers 3..4 */
TIM3->CCR3 = 500;
TIM3->CCR4 = 500;
/** setup channels 3..4 to corresponding output pin */
TIM3->CCER |= TIM_CCER_CC3E | TIM_CCER_CC4E;



Обращаю внимание на то что следует внимательно прочитать дш и мануал по мк для того чтобы настроить определенные функции. Т.к большинство функций в мк с малым корпусом распределено так что они многократно накладываются друг на друга.

Прерывание для пина 0, также необходимо переделать:


/* EXTI line0 interrupt */
void EXTI_L0_Handler(void) {
    if (EXTI->PR & (1 << 0)) {
        if (TIM3->CCR3 == 500) {
            TIM3->CCR3 = 100;
            TIM3->CCR4 = 900;
        }
        else {
            TIM3->CCR3 = 500;
            TIM3->CCR4 = 500;
        }
        EXTI->PR |= (1 << 0);
    }
   
}



И наконец полные файлы проекта.
main.c:




startup.c:


Соберем новый проект и загрузим его в мк:

nis@jane ~/stm32/examples/05-tim3 $ make all write
arm-softfloat-linux-gnueabi-gcc -g -O2 -mlittle-endian -mthumb -ffreestanding -nostdlib -nostdinc -mcpu=cortex-m3 -DSTM32F10X_MD_VL -I. -I../../stlink/example/libs_stm/inc/base -I../../stlink/example/libs_stm/inc/core_support -I../../stlink/example/libs_stm/inc/device_support -Wl,-T,stm32f100xb_flash.ld   -c -o startup.o startup.c
arm-softfloat-linux-gnueabi-gcc -g -O2 -mlittle-endian -mthumb -ffreestanding -nostdlib -nostdinc -mcpu=cortex-m3 -DSTM32F10X_MD_VL -I. -I../../stlink/example/libs_stm/inc/base -I../../stlink/example/libs_stm/inc/core_support -I../../stlink/example/libs_stm/inc/device_support -Wl,-T,stm32f100xb_flash.ld -o firmware.elf main.o sys_init.o startup.o -L.
arm-softfloat-linux-gnueabi-objcopy -O binary firmware.elf firmware.bin
st-flash write v1 firmware.bin 0x8000000
2012-03-01T11:06:16 INFO src/stlink-common.c: Loading device parameters....
2012-03-01T11:06:16 INFO src/stlink-common.c: Device connected is: F1 Medium-density Value Line device
2012-03-01T11:06:16 INFO src/stlink-common.c: SRAM size: 0x2000 bytes (8 KiB), Flash: 0x20000 bytes (128 KiB) in pages of 1024 bytes
2012-03-01T11:06:16 INFO src/stlink-sg.c: Successfully opened a stlink v1 debugger
2012-03-01T11:06:16 INFO src/stlink-common.c: Attempting to write 648 (0x288) bytes to stm32 address: 134217728 (0x8000000)
2012-03-01T11:06:16 INFO src/stlink-common.c: Erasing flash page at addr: 0x8000000
2012-03-01T11:06:16 INFO src/stlink-common.c: Successfully unlocked flash
2012-03-01T11:06:16 INFO src/stlink-common.c: Finished erasing 1 pages of 1024 (0x400) bytes
2012-03-01T11:06:16 INFO src/stlink-common.c: Starting Flash write for VL core id
2012-03-01T11:06:16 INFO src/stlink-common.c: Successfully loaded flash loader in sram
2012-03-01T11:06:16 INFO src/stlink-common.c: Writing flash block 0 of size 64 (0x40)
...
2012-03-01T11:06:16 INFO src/stlink-common.c: Successfully unlocked flash
2012-03-01T11:06:16 INFO src/stlink-common.c: Writing flash block 10 of size 64 (0x40)
2012-03-01T11:06:16 INFO src/stlink-common.c: Successfully unlocked flash
2012-03-01T11:06:16 INFO src/stlink-common.c: Starting verification of write complete
2012-03-01T11:06:16 INFO src/stlink-common.c: Flash written and verified! jolly good!
И видео работы:

На этом все.