分享一个大学竞赛代码,基于STM32F103的红外遥控小车

项目简介

采用 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

环境自己搭建,不会可以私信我。

  • 19
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值