写一篇基于STM32F103T8C6的红外遥控电机调速系统并能通过显示屏显示转速和方向的设计的完整程序
本设计基于STM32F103T8C6开发板,实现了一个红外遥控电机调速系统。该系统可以通过红外遥控器控制电机的转速和转向,并能通过显示屏显示电机的转速和方向。下面是该系统的完整程序。
一、硬件设计
本系统的硬件设计主要包括以下模块:
-
STM32F103T8C6开发板
-
红外接收模块
-
电机驱动模块
-
显示屏模块
其中,STM32F103T8C6开发板作为系统的核心控制器,红外接收模块用于接收红外遥控器的信号,电机驱动模块用于控制电机的转速和转向,显示屏模块用于显示电机的转速和方向。
二、软件设计
本系统的软件设计主要包括以下模块:
-
红外遥控信号解码模块
-
电机控制模块
-
显示模块
其中,红外遥控信号解码模块用于解码红外遥控器发送的信号,电机控制模块根据解码结果控制电机的转速和转向,显示模块用于显示电机的转速和方向。
三、程序代码
以下是本系统的完整程序代码。
#include "stm32f10x.h"
#define IR_PIN GPIO_Pin_1
#define IR_PORT GPIOA
#define IR_EXTI EXTI_Line1
#define IR_NVIC_IRQn EXTI1_IRQn
#define IR_TIM TIM2
#define IR_TIM_IRQn TIM2_IRQn
#define MOTOR_PIN GPIO_Pin_2
#define MOTOR_PORT GPIOA
#define MOTOR_TIM TIM3
#define MOTOR_TIM_IRQn TIM3_IRQn
#define MOTOR_PRESCALER 239
#define MOTOR_PERIOD 999
#define LCD_PORT GPIOB
#define LCD_RS GPIO_Pin_10
#define LCD_RW GPIO_Pin_11
#define LCD_EN GPIO_Pin_12
#define LCD_D4 GPIO_Pin_5
#define LCD_D5 GPIO_Pin_6
#define LCD_D6 GPIO_Pin_7
#define LCD_D7 GPIO_Pin_8
void IR_Init(void);
void MOTOR_Init(void);
void LCD_Init(void);
void LCD_WriteCommand(uint8_t cmd);
void LCD_WriteData(uint8_t data);
void LCD_WriteString(char *str);
void LCD_SetCursor(uint8_t row, uint8_t col);
void LCD_Clear(void);
void delay_us(uint32_t us);
void delay_ms(uint32_t ms);
uint8_t IR_Data[4] = {0};
uint8_t IR_Index = 0;
uint8_t IR_Flag = 0;
uint16_t MOTOR_Speed = 0;
int8_t MOTOR_Direction = 0;
int main(void)
{
IR_Init();
MOTOR_Init();
LCD_Init();
LCD_Clear();
LCD_SetCursor(0, 0);
LCD_WriteString("Motor Speed: 0");
LCD_SetCursor(1, 0);
LCD_WriteString("Motor Direction: F");
while (1)
{
if (IR_Flag)
{
IR_Flag = 0;
if (IR_Data[2] == 0x0E)
{
switch (IR_Data[3])
{
case 0x01: // Up
if (MOTOR_Speed < 1000)
{
MOTOR_Speed += 100;
}
break;
case 0x02: // Down
if (MOTOR_Speed > 100)
{
MOTOR_Speed -= 100;
}
break;
case 0x04: // Left
MOTOR_Direction = -1;
break;
case 0x05: // Right
MOTOR_Direction = 1;
break;
case 0x06: // OK
MOTOR_Direction = 0;
break;
}
}
IR_Index = 0;
IR_Data[0] = 0;
IR_Data[1] = 0;
IR_Data[2] = 0;
IR_Data[3] = 0;
}
MOTOR_TIM->CCR1 = MOTOR_Speed;
if (MOTOR_Direction == -1)
{
GPIO_ResetBits(MOTOR_PORT, MOTOR_PIN);
}
else if (MOTOR_Direction == 1)
{
GPIO_SetBits(MOTOR_PORT, MOTOR_PIN);
}
else
{
GPIO_ResetBits(MOTOR_PORT, MOTOR_PIN);
GPIO_SetBits(MOTOR_PORT, MOTOR_PIN);
}
char str[16];
sprintf(str, "Motor Speed: %d", MOTOR_Speed);
LCD_SetCursor(0, 0);
LCD_WriteString(str);
if (MOTOR_Direction == -1)
{
LCD_SetCursor(1, 0);
LCD_WriteString("Motor Direction: B");
}
else if (MOTOR_Direction == 1)
{
LCD_SetCursor(1, 0);
LCD_WriteString("Motor Direction: F");
}
else
{
LCD_SetCursor(1, 0);
LCD_WriteString("Motor Direction: S");
}
delay_ms(100);
}
}
void IR_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
EXTI_InitTypeDef EXTI_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
GPIO_InitStruct.GPIO_Pin = IR_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(IR_PORT, &GPIO_InitStruct);
EXTI_InitStruct.EXTI_Line = IR_EXTI;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = IR_NVIC_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x01;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
TIM_TimeBaseInitTypeDef TIM_InitStruct;
TIM_InitStruct.TIM_Prescaler = 7199;
TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_InitStruct.TIM_Period = 9999;
TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(IR_TIM, &TIM_InitStruct);
TIM_ICInitTypeDef TIM_ICInitStruct;
TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStruct.TIM_ICFilter = 0x0F;
TIM_ICInit(IR_TIM, &TIM_ICInitStruct);
TIM_Cmd(IR_TIM, ENABLE);
TIM_ITConfig(IR_TIM, TIM_IT_CC1, ENABLE);
}
void MOTOR_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_InitStruct;
TIM_OCInitTypeDef TIM_OCInitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
GPIO_InitStruct.GPIO_Pin = MOTOR_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(MOTOR_PORT, &GPIO_InitStruct);
TIM_InitStruct.TIM_Prescaler = MOTOR_PRESCALER;
TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_InitStruct.TIM_Period = MOTOR_PERIOD;
TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(MOTOR_TIM, &TIM_InitStruct);
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_Pulse = 0;
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(MOTOR_TIM, &TIM_OCInitStruct);
TIM_Cmd(MOTOR_TIM, ENABLE);
}
void LCD_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStruct.GPIO_Pin = LCD_RS | LCD_RW | LCD_EN | LCD_D4 | LCD_D5 | LCD_D6 | LCD_D7;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LCD_PORT, &GPIO_InitStruct);
GPIO_SetBits(LCD_PORT, LCD_RS);
GPIO_ResetBits(LCD_PORT, LCD_RW);
GPIO_ResetBits(LCD_PORT, LCD_EN);
GPIO_ResetBits(LCD_PORT, LCD_D4);
GPIO_ResetBits(LCD_PORT, LCD_D5);
GPIO_ResetBits(LCD_PORT, LCD_D6);
GPIO_ResetBits(LCD_PORT, LCD_D7);
delay_ms(20);
LCD_WriteCommand(0x28);
delay_us(39);
LCD_WriteCommand(0x28);
delay_us(39);
LCD_WriteCommand(0x28);
delay_us(39);
LCD_WriteCommand(0x0C);
delay_us(39);
LCD_WriteCommand(0x01);
delay_ms(2);
LCD_WriteCommand(0x06);
delay_us(39);
}
void LCD_WriteCommand(uint8_t cmd)
{
GPIO_ResetBits(LCD_PORT, LCD_RS);
GPIO_ResetBits(LCD_PORT, LCD_RW);
GPIO_SetBits(LCD_PORT, LCD_EN);
GPIO_WriteBit(LCD_PORT, LCD_D4, (cmd & 0x10) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(LCD_PORT, LCD_D5, (cmd & 0x20) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(LCD_PORT, LCD_D6, (cmd & 0x40) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(LCD_PORT, LCD_D7, (cmd & 0x80) ? Bit_SET : Bit_RESET);
delay_us(1);
GPIO_ResetBits(LCD_PORT, LCD_EN);
delay_us(1);
GPIO_SetBits(LCD_PORT, LCD_EN);
GPIO_WriteBit(LCD_PORT, LCD_D4, (cmd & 0x01) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(LCD_PORT, LCD_D5, (cmd & 0x02) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(LCD_PORT, LCD_D6, (cmd & 0x04) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(LCD_PORT, LCD_D7, (cmd & 0x08) ? Bit_SET : Bit_RESET);
delay_us(1);
GPIO_ResetBits(LCD_PORT, LCD_EN);
delay_us(39);
}
void LCD_WriteData(uint8_t data)
{
GPIO_SetBits(LCD_PORT, LCD_RS);
GPIO_ResetBits(LCD_PORT, LCD_RW);
GPIO_SetBits(LCD_PORT, LCD_EN);
GPIO_WriteBit(LCD_PORT, LCD_D4, (data & 0x10) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(LCD_PORT, LCD_D5, (data & 0x20) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(LCD_PORT, LCD_D6, (data & 0x40) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(LCD_PORT, LCD_D7, (data & 0x80) ? Bit_SET : Bit_RESET);
delay_us(1);
GPIO_ResetBits(LCD_PORT, LCD_EN);
delay_us(1);
GPIO_SetBits(LCD_PORT, LCD_EN);
GPIO_WriteBit(LCD_PORT, LCD_D4, (data & 0x01) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(LCD_PORT, LCD_D5, (data & 0x02) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(LCD_PORT, LCD_D6, (data & 0x04) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(LCD_PORT, LCD_D7, (data & 0x08) ? Bit_SET : Bit_RESET);
delay_us(1);
GPIO_ResetBits(LCD_PORT, LCD_EN);
delay_us(39);
}
void LCD_WriteString(char *str)
{
while (*str)
{
LCD_WriteData(*str++);
}
}
void LCD_SetCursor(uint8_t row, uint8_t col)
{
uint8_t addr = 0x80;
if (row == 1)
{
addr += 0x40;
}
addr += col;
LCD_WriteCommand(addr);
delay_us(39);
}
void LCD_Clear(void)
{
LCD_WriteCommand(0x01);
delay_ms(2);
}
void delay_us(uint32_t us)
{
us *= 8;
while (us--)
{
__NOP();
}
}
void delay_ms(uint32_t ms)
{
while (ms--)
{
delay_us(1000);
}
}
void EXTI1_IRQHandler(void)
{
if (EXTI_GetITStatus(IR_EXTI) != RESET)
{
EXTI_ClearITPendingBit(IR_EXTI);
uint16_t value = TIM_GetCapture1(IR_TIM);
uint16_t delta = value - IR_Data[IR_Index];
IR_Data[IR_Index++] = value;
if (IR_Index >= 4)
{
IR_Index = 0;
IR_Flag = 1;
}
if (delta > 2500)
{
IR_Index = 0;
IR_Data[0] = 0;
IR_Data[1] = 0;
IR_Data[2] = 0;
IR_Data[3] = 0;
}
}
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(IR_TIM, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(IR_TIM, TIM_IT_CC1);
}
}
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(MOTOR_TIM, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(MOTOR_TIM, TIM_IT_CC1);
}
}
四、总结
本设计通过STM32F103T8C6开发板实现了一个红外遥控电机调速系统,可以通过红外遥控器控制电机的转速和转向,并能通过显示屏显示电机的转速和方向。该系统的设计可以扩展至其他应用领域,具有一定的实用性和参考价值。
原文地址: https://www.cveoy.top/t/topic/AOA 著作权归作者所有。请勿转载和采集!