STM32: управление сервомотором с компьютера

Хороший пример, объединяющий в себе работу с USART, таймерами и прерываниями — это сервомоторчик, управляемый компьютером.

Сервомотор имеет три контакта — земля, сигнал и питание. Обычно они окрашены в стандартные цвета, земля — чёрная или коричневая, питание красное, а сигнал — жёлтый.

Управление сервомотором очень хорошо ложится на модуль ШИМ, поскольку сервомотор принимает повторяющийся сигнал с длительностью единицы, пропорциональной углу поворота. Конкретный период следования импульсов совершенно неважен, он лишь должен быть в пределах 20-50 Гц, но многие сервы позволяют и большую частоту импульсов. Важна лишь длительность «единицы», которую мы и смоделируем с помощью ШИМ.

Управлять будем через терминал, нажатие кнопки «w» будет увеличивать угол отклонения качалки, кнопка «s» будет его уменьшать. Используем USART1, ремапленный на пины PB6/PB7.

Управление по USART сервомотором через STM32VLDiscovery

#include "stm32f10x.h"

int main(void)
{
RCC->APB2ENR|= RCC_APB2ENR_USART1EN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN;
AFIO->MAPR  |= AFIO_MAPR_USART1_REMAP;
GPIOB->CRL  |= GPIO_CRL_CNF6_1 | GPIO_CRL_MODE6_0 | GPIO_CRL_CNF7_0;
USART1->BRR = 0x9C4/1;
USART1->CR1 |= USART_CR1_TE | USART_CR1_RE;
USART1->CR1 |= USART_CR1_UE;
USART1->CR1 |= USART_CR1_RXNEIE;
NVIC_EnableIRQ(USART1_IRQn);

// Включаем порт ввода-вывода и настраиваем ножку PC7
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_Init(GPIOB, &GPIO_InitStructure);

// Включаем тактирование таймера
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

// Настраиваем таймер на использование 2 канала
TIM3->CCER |= TIM_CCER_CC4E | TIM_CCER_CC4P;

// Переводим 2 канал в режим ШИМ2
TIM3->CCMR2|= TIM_CCMR2_OC4M_0 | TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2;

// Настраиваем прескалер
TIM3->PSC = 1000;

// Настраиваем период таймера = 1000 циклов
TIM3->ARR = 400;

// Настраиваем скважность = 200 циклов
TIM3->CCR4 = 20;

// Включаем таймер
TIM3->CR1 |= TIM_CR1_CEN;

while(1);
}

void USART1_IRQHandler(void) {
if (USART1->SR & USART_SR_RXNE) {
USART1->SR&=~USART_SR_RXNE;

if(USART1->DR=='w') if(TIM3->CCR4<55) TIM3->CCR4+=1;
if(USART1->DR=='s') if(TIM3->CCR4>15) TIM3->CCR4-=1;
}
}

Ничего сложного, не правда ли?

Как всегда, вы можете скачать весь проект (для IAR): Servo_USART_Example.zip.