项目简介
采用 STM32F103 芯片+ YL-86(电机模块)+L9110s(驱动电机芯片)+HC-SR04(超声测距模块)等,实现遥控和躲避障碍物功能。支持红外遥控。
从最简单的模块开始:
led.c
#include "led.h"
//函数功能:LED初始化
//函数说明:LED1-PC0;LED2-PC1;LED3-PC2
void LED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2;//引脚
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;//输出速度
GPIO_Init(GPIOC,&GPIO_InitStruct);
}
led.h
#ifndef LED_H
#define LED_H
#include "stm32f10x.h"
void LED_Init(void);
#define LED1_ON GPIO_ResetBits(GPIOC, GPIO_Pin_0)
#define LED1_OFF GPIO_SetBits(GPIOC, GPIO_Pin_0)
#define LED1_FZ GPIOC->ODR^=0x01
#define LED2_ON GPIO_ResetBits(GPIOC, GPIO_Pin_1)
#define LED2_OFF GPIO_SetBits(GPIOC, GPIO_Pin_1)
#define LED2_FZ GPIOC->ODR^=0x02
#define LED3_ON GPIO_ResetBits(GPIOC, GPIO_Pin_2)
#define LED3_OFF GPIO_SetBits(GPIOC, GPIO_Pin_2)
#endif
key.c
#include "key.h"
#include "delay.h"
//函数功能:KEY初始化
//函数说明:KEY1--PA0(按键按下--低)
void KEY_Init(void)
{
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOA,&GPIO_InitStruct);
}
key.h
#ifndef KEY_H
#define KEY_H
#include "stm32f10x.h"
void KEY_Init(void);
u32 Get_Key_Time(void);
u8 Key_Mode(void);
#define KEY1_PRESS GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==0
#endif
delay.c
#include "delay.h"
// u8 u16 u32
//函数功能:ms级延时函数
//函数参数:u16 t 定时时长(0-1864)
//函数返回值:无
void delay_ms(u16 t)
{
//1、选择时钟源--21Mhz;
SysTick->CTRL &=~ (1<<2);
//2、填入计数值;
SysTick->LOAD = t*9000-1;
//3、开启计数器;
SysTick->CTRL |= (1<<0);
//4、判断计数器计数是否结束(CTRL的第16位)
while((SysTick->CTRL&(1<<16))==0);
//5、关闭计数器;
SysTick->CTRL &=~ (1<<0);
}
void delay_us(u16 t)
{
//1、选择时钟源--21Mhz;
SysTick->CTRL &=~ (1<<2);
//2、填入计数值;
SysTick->LOAD = t*9-1;
//3、开启计数器;
SysTick->CTRL |= (1<<0);
//4、判断计数器计数是否结束(CTRL的第16位)
while((SysTick->CTRL&(1<<16))==0);
//5、关闭计数器;
SysTick->CTRL &=~ (1<<0);
}
delay.h
#ifndef DELAY_H
#define DELAY_H
#include "stm32f10x.h"
void delay_ms(u16 t);
void delay_us(u16 t);
#endif
beep.c
#include "beep.h"
//函数功能:BEEP初始化
//函数说明:BEEP-PA15;
void BEEP_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
AFIO->MAPR |=1<<25;
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15; //引脚
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz; //输出速度
GPIO_Init(GPIOA,&GPIO_InitStruct);
BEEP_OFF;
}
beep.h
#ifndef BEEP_H
#define BEEP_H
#include "stm32f10x.h"
void BEEP_Init(void);
#define BEEP_ON GPIO_SetBits(GPIOA, GPIO_Pin_15)
#define BEEP_OFF GPIO_ResetBits(GPIOA, GPIO_Pin_15)
#endif
串口
#include "usart1.h"
//函数功能:USART1初始化函数
//函数参数:u32 bound 波特率
//函数说明:USART1_TX--PA9;USART1_RX--PA10
void Usart1_Init(u32 bound)
{
//1、开时钟:APB2---USART1,GPIOA;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//2、对PA9和PA10进行初始化:工作模式---复用模式
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //复用模式
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; //引脚
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;//中速
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA,&GPIO_InitStruct);
//3、USART1进行初始化=》波特率,硬件流控制,校验位,模式,停止位,字长
USART_InitTypeDef USART_InitStruct;
USART_InitStruct.USART_BaudRate = bound; //波特率:函数形参
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不用硬件流控制
USART_InitStruct.USART_Parity = USART_Parity_No; //不用校验位
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //全双工
USART_InitStruct.USART_StopBits = USART_StopBits_1; //停止位1bit
USART_InitStruct.USART_WordLength = USART_WordLength_8b; //字长8bit
USART_Init(USART1, &USART_InitStruct);
usart_config();
//4、使能USART1
USART_Cmd(USART1,ENABLE);
}
//USART1发送单字节数据
void Usart1_SendByte(u8 data)
{
while(!USART_GetFlagStatus(USART1,USART_FLAG_TXE));
USART_SendData(USART1,data);
}
//USART1接收单字节数据
u8 Usart1_RecByte(void)
{
while(!USART_GetFlagStatus(USART1,USART_FLAG_RXNE));
return USART_ReceiveData(USART1);
}
//USART1发送字符串函数
void Usart1_SendStr(char *buff)
{
do{
Usart1_SendByte(*buff);
buff++;
}while(*buff!='\0');
}
//USART1接收字符串
void Usart1_RecStr(char *buff)
{
char data;
do
{
data = Usart1_RecByte();
*buff=data;
buff++;
}while((data != '\n')&&(data != '\r'));
*buff='\0';
}
//函数功能:usart中断初始化
//函数参数:无
//函数返回值:无
//功能说明:RXNE,IDLE--接收中断
void usart_config(void)
{
USART_ITConfig (USART1, USART_IT_RXNE, ENABLE);
USART_ITConfig (USART1, USART_IT_IDLE, ENABLE);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel =USART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd =ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority =1;
NVIC_Init(&NVIC_InitStruct);
}
typedef struct
{
char buff[100];
int cnt;
}U1_REC;
U1_REC u1={0};
void USART1_IRQHandler(void)
{
u8 data;
if( USART_GetITStatus (USART1, USART_IT_RXNE))
{
data=USART_ReceiveData (USART1);
u1.buff[u1.cnt]=data;
u1.cnt++;
}
if(USART_GetITStatus (USART1, USART_IT_IDLE))
{
USART1->SR;
USART1->DR;
u1.buff[u1.cnt]='\0';
printf("数据:%s\r\n",u1.buff);
printf("长度:%d\r\n",u1.cnt);
printf("数据接收完毕\r\n");
u1.cnt=0;
}
}
#pragma import(__use_no_semihosting_swi) //取消半主机状态
struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
//printf()的子函数
int fputc(int ch, FILE *f)
{
//替换为开发者重定向的发送单字节函数
Usart1_SendByte(ch);
return (ch);
}
int ferror(FILE *f) {
/* Your implementation of ferror */
return EOF;
}
void _ttywrch(int ch) {
//替换为开发者重定向的发送单字节函数
Usart1_SendByte(ch);
}
void _sys_exit(int return_code) {
label: goto label; /* endless loop */
}
串口头文件
#ifndef USART1_H
#define USART1_H
#include "stm32f10x.h"
#include "stdio.h"
void Usart1_Init(u32 bound);
void Usart1_SendByte(u8 data);
u8 Usart1_RecByte(void);
void Usart1_SendStr(char *buff);
void Usart1_RecStr(char *buff);
void usart_config(void);
#endif
lcd.c
lcd和芯片采用SPI通讯
#include "lcd.h"
#include "delay.h"
//函数功能:SPI初始化,引脚初始化
//函数说明:
/*
LCD_BL PA4
LCD_CS PA5
LCD_DC PA12
LCD_RES PB12
LCD_SCK PB13->SPI2
LCD_MOSI PB15->SPI2
*/
void LCD_Port_Init(void)
{
//1、开启GPIO和SPI2时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
//2、引脚初始化
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_12;//引脚
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;//输出速度
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;//引脚
GPIO_Init(GPIOB,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//推挽复用输出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_15;//引脚
GPIO_Init(GPIOB,&GPIO_InitStruct);
//3、SPI2初始化
SPI_InitTypeDef SPI_InitStruct;
SPI_InitStruct.SPI_BaudRatePrescaler =SPI_BaudRatePrescaler_4;
SPI_InitStruct.SPI_CPHA =SPI_CPHA_1Edge;
SPI_InitStruct.SPI_CPOL =SPI_CPOL_Low; //空闲电平为低
SPI_InitStruct.SPI_CRCPolynomial =0X0007; //CRC数据校验8/16 这里配置为8位
SPI_InitStruct.SPI_DataSize =SPI_DataSize_8b; //数据宽度8/16这里配置为8位
SPI_InitStruct.SPI_Direction =SPI_Direction_2Lines_FullDuplex;//数据传输方式这里配置全双工
SPI_InitStruct.SPI_FirstBit =SPI_FirstBit_MSB; //数据发送方式,这里配置高位在前
SPI_InitStruct.SPI_Mode =SPI_Mode_Master; //主机(单片机)配置主模式
SPI_InitStruct.SPI_NSS =SPI_NSS_Soft; //片选引脚选软件模式
SPI_Init (SPI2, &SPI_InitStruct);
SPI_Cmd (SPI2, ENABLE);
LCD_RES_H;
LCD_CS_H;
}
//SPI2发送单字节函数
u8 SPI2_SendByte(u8 data)
{
while(!SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE));
SPI_I2S_SendData(SPI2,data);
while(!SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE));
return SPI_I2S_ReceiveData(SPI2);
}
//STM32->ST7735S:命令
//1、CS_L
//2、DC_L
void LCD_Send_Command(u8 command)
{
LCD_CS_L; //选中芯片
LCD_DC_L; //发送命令
SPI2_SendByte(command);
LCD_CS_H; //释放芯片
}
//STM32->ST7735S:参数
//1、CS_L
//2、DC_H
void LCD_Send_Parameter(u8 parameter)
{
LCD_CS_L; //选中芯片
LCD_DC_H; //发送参数
SPI2_SendByte(parameter);
LCD_CS_H; //释放芯片
}
//STM32->ST7735S:16bit数据
//1、CS_L
//2、DC_H
void LCD_Send_Data(u16 data)
{
LCD_CS_L; //选中芯片
LCD_DC_H; //发送参数
SPI2_SendByte((u8)(data>>8));
SPI2_SendByte((u8)data);
LCD_CS_H; //释放芯片
}
//设置位置函数
//函数参数:
/*
起始列地址:u8 xs
结束列地址:u8 xe
起始行地址:u8 ys
结束行地址:u8 ye
*/
void LCD_Set_Address(u8 xs,u8 xe,u8 ys,u8 ye)
{
LCD_Send_Command(0X2A);//设置列地址
LCD_Send_Data(xs); //起始列
LCD_Send_Data(xe); //终止列
LCD_Send_Command(0X2B);//设置列地址
LCD_Send_Data(ys); //起始行
LCD_Send_Data(ye); //终止行
LCD_Send_Command(0X2C);//写入存储器
}
//向一个像素点写入颜色数据
//函数参数:起始列u8 xs 起始行u8 ys 颜色数据:u16 color
void LCD_Show_Point(u8 xs,u8 ys,u16 color)
{
LCD_Set_Address(xs,xs,ys,ys);
LCD_Send_Data(color);
}
//清屏
void LCD_Clear(u8 xs,u8 xe,u8 ys,u8 ye,u16 color)
{
LCD_Set_Address(xs,xe,ys,ye);//设置清屏区域
for(u16 i=0;i<(xe-xs+1)*(ye-ys+1);i++)
{
LCD_Send_Data(color);
}
}
//LCD初始化
void LCD_Init(void)
{
LCD_Port_Init();
LCD_RES_L;
delay_ms(100);
LCD_RES_H;
delay_ms(50);
//LCD Init For 1.44Inch LCD Panel with ST7735R.
LCD_Send_Command(0x11); //退出休眠模式
delay_ms (120);
//ST7735R Frame Rate 850Khz/((1 x 2 + 40) x (LINE + 44 + 45 +2))
LCD_Send_Command(0xB1); //设置全色正常模式的帧频率
LCD_Send_Parameter(0x01); //RTNA=0X01
LCD_Send_Parameter(0x2C); //FPA =0X2C
LCD_Send_Parameter(0x2D); //BPA =0X2D
LCD_Send_Command(0xB2);
LCD_Send_Parameter(0x01);
LCD_Send_Parameter(0x2C);
LCD_Send_Parameter(0x2D);
LCD_Send_Command(0xB3);
LCD_Send_Parameter(0x01);
LCD_Send_Parameter(0x2C);
LCD_Send_Parameter(0x2D);
LCD_Send_Parameter(0x01);
LCD_Send_Parameter(0x2C);
LCD_Send_Parameter(0x2D);
LCD_Send_Command(0xB4); //Column inversion
LCD_Send_Parameter(0x07);
//ST7735R Power Sequence
LCD_Send_Command(0xC0);
LCD_Send_Parameter(0xA2);
LCD_Send_Parameter(0x02);
LCD_Send_Parameter(0x84);
LCD_Send_Command(0xC1);
LCD_Send_Parameter(0xC5);
LCD_Send_Command(0xC2);
LCD_Send_Parameter(0x0A);
LCD_Send_Parameter(0x00);
LCD_Send_Command(0xC3);
LCD_Send_Parameter(0x8A);
LCD_Send_Parameter(0x2A);
LCD_Send_Command(0xC4);
LCD_Send_Parameter(0x8A);
LCD_Send_Parameter(0xEE);
LCD_Send_Command(0xC5); //VCOM
LCD_Send_Parameter(0x0E);
LCD_Send_Command(0x36); //MX, MY, RGB mode
LCD_Send_Parameter(0xC0);
//ST7735R Gamma Sequence
LCD_Send_Command(0xe0);
LCD_Send_Parameter(0x0f);
LCD_Send_Parameter(0x1a);
LCD_Send_Parameter(0x0f);
LCD_Send_Parameter(0x18);
LCD_Send_Parameter(0x2f);
LCD_Send_Parameter(0x28);
LCD_Send_Parameter(0x20);
LCD_Send_Parameter(0x22);
LCD_Send_Parameter(0x1f);
LCD_Send_Parameter(0x1b);
LCD_Send_Parameter(0x23);
LCD_Send_Parameter(0x37);
LCD_Send_Parameter(0x00);
LCD_Send_Parameter(0x07);
LCD_Send_Parameter(0x02);
LCD_Send_Parameter(0x10);
LCD_Send_Command(0xe1);
LCD_Send_Parameter(0x0f);
LCD_Send_Parameter(0x1b);
LCD_Send_Parameter(0x0f);
LCD_Send_Parameter(0x17);
LCD_Send_Parameter(0x33);
LCD_Send_Parameter(0x2c);
LCD_Send_Parameter(0x29);
LCD_Send_Parameter(0x2e);
LCD_Send_Parameter(0x30);
LCD_Send_Parameter(0x30);
LCD_Send_Parameter(0x39);
LCD_Send_Parameter(0x3f);
LCD_Send_Parameter(0x00);
LCD_Send_Parameter(0x07);
LCD_Send_Parameter(0x03);
LCD_Send_Parameter(0x10);
LCD_Send_Command(0x2a);
LCD_Send_Parameter(0x00);
LCD_Send_Parameter(0x00);
LCD_Send_Parameter(0x00);
LCD_Send_Parameter(0x7f);
LCD_Send_Command(0x2b);
LCD_Send_Parameter(0x00);
LCD_Send_Parameter(0x00);
LCD_Send_Parameter(0x00);
LCD_Send_Parameter(0x9f);
LCD_Send_Command(0xF0); //Enable test command
LCD_Send_Parameter(0x01);
LCD_Send_Command(0xF6); //Disable ram power save mode
LCD_Send_Parameter(0x00);
LCD_Send_Command(0x3A); //65k mode
LCD_Send_Parameter(0x05);
LCD_Send_Command(0x29);//Display on
LCD_BL_H;
LCD_Clear(0,131,0,161,0XFFFF); //128*160
}
void lcd_display_gb2312(u8* p,int size,int x,int y,u16 zt_color, u16 bj_color)
{
LCD_Set_Address(x,x+size-1,y,y+size-1);
for(int i = 0; i<size*size/8;i++)
{
for(int j=0;j<8;j++)
{
if(p[i] & (1<<(7-j)))
{
LCD_Send_Data(zt_color);
}
else
{
LCD_Send_Data(bj_color);
}
}
}
}
lcd.h
#ifndef LCD_H
#define LCD_H
#include "stm32f10x.h"
#include "string.h"
#define LCD_CS_L GPIO_ResetBits(GPIOA, GPIO_Pin_5)
#define LCD_CS_H GPIO_SetBits(GPIOA, GPIO_Pin_5)
#define LCD_RES_L GPIO_ResetBits(GPIOB, GPIO_Pin_12)
#define LCD_RES_H GPIO_SetBits(GPIOB, GPIO_Pin_12)
#define LCD_DC_L GPIO_ResetBits(GPIOA, GPIO_Pin_12)
#define LCD_DC_H GPIO_SetBits(GPIOA, GPIO_Pin_12)
#define LCD_BL_L GPIO_ResetBits(GPIOA, GPIO_Pin_4)
#define LCD_BL_H GPIO_SetBits(GPIOA, GPIO_Pin_4)
void lcd_display_gb2312(u8* p,int size,int x,int y,u16 zt_color, u16 bj_color);
#define BLACK 0x0000 // 黑色
#define NAVY 0x000F // 深蓝色
#define DGREEN 0x03E0 // 深绿色
#define DCYAN 0x03EF // 深青色
#define MAROON 0x7800 // 深红色
#define PURPLE 0x780F // 紫色
#define OLIVE 0x7BE0 // 橄榄绿
#define LGRAY 0xC618 // 灰白色
#define DGRAY 0x7BEF // 深灰色
#define BLUE 0x001F // 蓝色
#define GREEN 0x07E0 // 绿色
#define CYAN 0x07FF // 青色
#define RED 0xF800 // 红色
#define MAGENTA 0xF81F // 品红
#define YELLOW 0xFFE0 // 黄色
#define WHITE 0xFFFF // 白色
void LCD_Port_Init(void);
void LCD_Init(void);
void LCD_Show_Picture(u8 es, u8 ys, u8 *buff);
void LCD_Clear(u8 xs,u8 xe,u8 ys,u8 ye,u16 color);
void LCD_Show_GB2312(u8 es, u8 ys,u8 size,u16 color,const char *buff);
void LCD_Show_ASCII(u8 es, u8 ys,u8 size,u16 color,const char *buff);
void LCD_Show_String(u8 es, u8 ys,u8 size,u16 color,u8 *buff);
void LCD_Draw_Line(u8 xs,u8 xe,u8 ys,u8 ye,u16 color);
#endif
电机模块,通过控制四个轮子不同的转速从而控制小车的前进方向
利用定时器的输出比较功能,控制占空比来控制转速
#include "motor.h"
u16 Car_Speed;
Car_Mode car_mode;
/*******************************************************************
* Function : 电机初始化
* Parameter : void
* Return : void
* Comment : 电机IA IB 控制 OA OB
IA1--PB8--TIM4_CH3 IB1--PB9--TIM4_CH4//右前轮P9
IA2--PB0--TIM3_CH3 IB2--PB1--TIM3_CH4//右后轮P10
IA3--PB6--TIM4_CH1 IB3--PB7--TIM4_CH2//左后轮P11
IA4--PA6--TIM3_CH1 IB4--PA7--TIM3_CH2//左前轮P12
********************************************************************/
void Motor_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //复用模式
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //引脚
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;//中速
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //复用模式
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9; //引脚
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;//中速
GPIO_Init(GPIOB,&GPIO_InitStruct);
TIMx_Config(RCC_APB1Periph_TIM3,TIM3);
TIMx_Config(RCC_APB1Periph_TIM4,TIM4);
}
/*******************************************************************
* Function : TIM初始化
* Parameter : 时钟的参数,TIMx
* Return : void
* Comment : 针对时基单元和输出比较初始化
********************************************************************/
void TIMx_Config(u32 RCC_APB1Periph,TIM_TypeDef *TIMx)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph,ENABLE);
TIM_TimeBaseInitTypeDef TIM_Struct;
TIM_Struct.TIM_ClockDivision =0;
TIM_Struct.TIM_CounterMode =TIM_CounterMode_Up;
TIM_Struct.TIM_Period =1000-1;//10ms
TIM_Struct.TIM_Prescaler =720-1;//0.01ms
TIM_Struct.TIM_RepetitionCounter =0;
TIM_TimeBaseInit(TIMx,&TIM_Struct);
TIM_OCInitTypeDef TIM_OCStruct;
TIM_OCStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCStruct.TIM_OutputState = ENABLE;
TIM_OC1Init(TIMx,&TIM_OCStruct);
TIM_OC2Init(TIMx,&TIM_OCStruct);
TIM_OC3Init(TIMx,&TIM_OCStruct);
TIM_OC4Init(TIMx,&TIM_OCStruct);
TIM_Cmd(TIMx,ENABLE);
}
/*******************************************************************
* Function : 小车模式控制
* Parameter : void
* Return : void
* Comment : 实现小车的前进,后退,停止,右转,左转
********************************************************************/
void Motor_Control(void)
{
if(car_mode==Car_Go)
{
TIM_SetCompare1(TIM3,Car_Speed);TIM_SetCompare2(TIM3,0);//左前轮
TIM_SetCompare1(TIM4,Car_Speed);TIM_SetCompare2(TIM4,0);//左后轮
TIM_SetCompare3(TIM4,Car_Speed);TIM_SetCompare4(TIM4,0);//右前轮
TIM_SetCompare3(TIM3,Car_Speed);TIM_SetCompare4(TIM3,0);//右后轮
}
if(car_mode==Car_Stop)
{
TIM_SetCompare1(TIM3,0);TIM_SetCompare2(TIM3,0);//左前轮
TIM_SetCompare1(TIM4,0);TIM_SetCompare2(TIM4,0);//左后轮
TIM_SetCompare3(TIM4,0);TIM_SetCompare4(TIM4,0);//右前轮
TIM_SetCompare3(TIM3,0);TIM_SetCompare4(TIM3,0);//右后轮
}
if(car_mode==Car_Back)
{
TIM_SetCompare1(TIM3,0);TIM_SetCompare2(TIM3,Car_Speed);//左前轮
TIM_SetCompare1(TIM4,0);TIM_SetCompare2(TIM4,Car_Speed);//左后轮
TIM_SetCompare3(TIM4,0);TIM_SetCompare4(TIM4,Car_Speed);//右前轮
TIM_SetCompare3(TIM3,0);TIM_SetCompare4(TIM3,Car_Speed);//右后轮
}
if(car_mode==Car_GoLeft)
{
TIM_SetCompare1(TIM3,0);TIM_SetCompare2(TIM3,0);//左前轮
TIM_SetCompare1(TIM4,0);TIM_SetCompare2(TIM4,Car_Speed);//左后轮
TIM_SetCompare3(TIM4,Car_Speed);TIM_SetCompare4(TIM4,0);//右前轮
TIM_SetCompare3(TIM3,Car_Speed);TIM_SetCompare4(TIM3,0);//右后轮
}
if(car_mode==Car_GoRight)
{
TIM_SetCompare1(TIM3,Car_Speed);TIM_SetCompare2(TIM3,0);//左前轮
TIM_SetCompare1(TIM4,Car_Speed);TIM_SetCompare2(TIM4,0);//左后轮
TIM_SetCompare3(TIM4,0);TIM_SetCompare4(TIM4,0);//右前轮
TIM_SetCompare3(TIM3,0);TIM_SetCompare4(TIM3,Car_Speed);//右后轮
}
}
motor.h
#ifndef MOTOR_H
#define MOTOR_H
#include "stm32f10x.h"
void Motor_Init(void);
void TIMx_Config(u32 RCC_APB1Periph,TIM_TypeDef *TIMx);
void Motor_Control(void);
typedef enum
{
Car_Go=1,
Car_Stop,
Car_Back,
Car_GoLeft,
Car_GoRight
} Car_Mode;
#endif
遥控模块(红外遥控)
#include "remote.h"
#include "stdio.h"
/*******************************************************************
* Function : 红外遥控初始化
* Parameter : void
* Return : void
* Comment : PA1--TIM2_CH2
********************************************************************/
void Remote_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; //复用模式
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1; //引脚
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;//中速
GPIO_Init(GPIOA,&GPIO_InitStruct);
TIM_TimeBaseInitTypeDef TIM_Struct;
TIM_Struct.TIM_ClockDivision =0;
TIM_Struct.TIM_CounterMode =TIM_CounterMode_Up;
TIM_Struct.TIM_Period =10000-1;//10ms
TIM_Struct.TIM_Prescaler =72-1;//1us
TIM_Struct.TIM_RepetitionCounter =0;
TIM_TimeBaseInit(TIM2,&TIM_Struct);
TIM_ICInitTypeDef TIM_ICStruct;
TIM_ICStruct.TIM_Channel =TIM_Channel_2;
TIM_ICStruct.TIM_ICFilter =0;
TIM_ICStruct.TIM_ICPolarity =TIM_ICPolarity_Rising;
TIM_ICStruct.TIM_ICPrescaler =TIM_ICPSC_DIV1;//一个边沿捕获一次
TIM_ICStruct.TIM_ICSelection =TIM_ICSelection_DirectTI;//TI2FP2直接映射
TIM_ICInit(TIM2,&TIM_ICStruct);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
TIM_ITConfig(TIM2,TIM_IT_CC2,ENABLE);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel =TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd =ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority =1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority =1;
NVIC_Init(&NVIC_InitStruct);
TIM_Cmd(TIM2,ENABLE);
}
//[4]:1 表示捕获到上升沿,0 没有捕获到上升沿
//[7]:1 表示接收到引导码,0 没有接收到引导码
//[6]:1 表示接收到一个完整的按键信息
//[5]:
//[0:3]:统计溢出次数
u8 RmtSta=0;
u16 Dval=0;//保存高电平的计数值
u32 RecData=0;//保存接收到的数据
u8 datal;
u8 datah;
u8 KeyValue=0;//保存键值
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_CC2))
{
if(Read_IR) //读取IR电平,高电平检测到上升沿
{
TIM_SetCounter(TIM2,0);//清零计数值
TIM2->CCER |=1<<5;//改为下降沿捕获
RmtSta |=1<<4;;//标志捕获到上升沿
}
else //捕获到下降沿
{
Dval=TIM_GetCapture2(TIM2);//获取当前计数值
TIM2->CCER &=~(1<<5);//改为下降沿捕获
if(RmtSta&(1<<4))//表明是一次完整的高电平
{
if(Dval>300&&Dval<800)//表明接收的是'0'
{
RecData<<=1;
RecData|=0;
}
if(Dval>1400&&Dval<1800)//表明接收的是'1'
{
RecData<<=1;
RecData|=1;
}
if(Dval>2200&&Dval<2600)//表明接收的是连发码
{
RmtSta|=1<<6;//表明接到完整的按键信息
RmtSta|=1<<7;//表明接收到引导码
}
if(Dval>4200&&Dval<4700)//表明接收的是引导码
{
RmtSta|=1<<7;
RmtSta&=0Xf0;//溢出次数清0
}
}
RmtSta &=~(1<<4);
}
}
if(TIM_GetITStatus(TIM2,TIM_IT_Update))
{
if(RmtSta&(1<<6))//数据完整
{
datah=RecData>>24;
datal=RecData>>16;
printf("接收的数据是%ld\r\n",RecData);
if(datah== ~datal)//if为真,地址码正确
{
datah=RecData>>8;
datal=RecData;
if(datah==~datal)//if为真,数据码正确
{
KeyValue=datah;
}
}
}
}
TIM_ClearITPendingBit(TIM2,TIM_IT_CC2);
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
romote.h
#ifndef REMOTE_H
#define REMOTE_H
#include "stm32f10x.h"
void Remote_Init(void);
#define Read_IR GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)
#endif
SR04测距模块,对这个模块不熟悉的可以下载它的datasheet学习一下
#include "sr04.h"
#include "delay.h"
/*******************************************************************
* Function : SR04初始化
* Parameter : void
* Return : void
* Comment : TRIG:PB14 ECHO:PC6
********************************************************************/
void SR04_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_14;//引脚
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;//输出速度
GPIO_Init(GPIOB,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOC,&GPIO_InitStruct);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
TIM_TimeBaseInitTypeDef TIM_Struct;
TIM_Struct.TIM_CounterMode =TIM_CounterMode_Up;
TIM_Struct.TIM_Period =2000-1;//计数周期
TIM_Struct.TIM_Prescaler =720-1;//计一个数0.01ms
TIM_TimeBaseInit(TIM1,&TIM_Struct);\
//产生更新事件将PSC的值填入到影子寄存器
TIM_GenerateEvent(TIM1,TIM_EventSource_Update);
TIM_ClearFlag(TIM1,TIM_FLAG_Update);
TIM_Cmd(TIM1,DISABLE);
//34cm/ms
}
/*******************************************************************
* Function : 获取测量距离
* Parameter : void
* Return : float
* Comment :
********************************************************************/
float SR04_Length(void)
{
//第一步:测距
SR04_TRIG_L;
SR04_TRIG_H;
delay_us(20);
SR04_TRIG_L;
//第二步:等待ECHO变为高电平
while(!GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_6));
TIM_SetCounter(TIM1,0);
TIM_Cmd(TIM1,ENABLE);
//第三步:等待ECHO变为低电平
while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_6));
TIM_Cmd(TIM1,DISABLE);
u16 count=TIM_GetCounter(TIM1);
//第四步:计算测量距离
float time=count*0.01;//高电平时长 ms
float length=time*17.0;//cm
return length ;
}
SR04.h
#ifndef SR04_H
#define SR04_H
#include "stm32f10x.h"
#define SR04_TRIG_L GPIO_ResetBits(GPIOB,GPIO_Pin_14);
#define SR04_TRIG_H GPIO_SetBits(GPIOB,GPIO_Pin_14);
float SR04_Length(void);
void SR04_Init(void);
#endif
最后的main函数
#include "main.h"
extern u16 Car_Speed;
extern Car_Mode car_mode;
extern u8 KeyValue;
int main(void)
{
LED_Init();
LCD_Init();
KEY_Init();
LED1_ON;
BEEP_Init();
Usart1_Init(115200);
SR04_Init();
Motor_Init();
Remote_Init();
while(1)
{
if(KeyValue!=0)
{
printf("KeyValue=%d\r\n",KeyValue);
}
}
}
main.h
#ifndef MAIN_H
#define MAIN_H
#include "stm32f10x.h"
#include "stdio.h"
#include "led.h"
#include "key.h"
#include "delay.h"
#include "beep.h"
#include "usart1.h"
#include "lcd.h"
#include "sr04.h"
#include "remote.h"
#include "motor.h"
#endif
编译环境Keil5
DEBUG ST-Link
环境自己搭建,不会可以私信我。