资源描述
《 嵌入式系统原理 》
课程设计说明书
题 目: 遥控智能小车
院 (系): 信息与电气工程学院
专业班级: 通信二班
学生姓名: 周波
学 号: 0904040209
指导教师: 罗朝辉
嵌入式系统原理 课程设计任务书
一、设计题目
遥控智能小车
二、设计主要内容
(1) 广泛查找文献资料,认真研究,反复论证,精心设计技术方案。
(2) 较为深入的掌握ARM处理器的体系结构、指令系统、编程方法,初步了解ARM应用系统的软硬件开发方法及手段,较熟练地掌握ARM处理器几种重要的片内外设(定时器、PLL、I2C、RTC等)的基本原理及编程方法,初步掌握ARM处理器外围电路的扩展方法。
(3) 在现有车模的基础上,以嵌入式ARM微处理器构成小车控制核心,同时加装声光电、红外线、超声波传感器、LED显示等外围设备,实现对小车的速度、位置、运行状况的实时测量,并将测量数据传送至处理器进行处理,然后由处理器根据所检测的各种数据实现对电动车的智能控制;
(4) 设计的智能小车应该能够实时显示时间、速度、里程,具有自动寻迹、寻光、避障功能,可程控行驶速度、准确定位停车。并有相应的声光电设备发出相关的提示或警示信息。
(5) 遥控方式可自选,系统通过遥控器可以控制小车的行驶方向、速度、起停等运行状态,要求要达到一定的控制精度、距离及范围,小车行驶速度应达到3m/s以上。
三、原始资料
硬件资源:四驱小车车模、STM32系统板、用于ARM处理器的JTAG仿真器、PC机Pentium100以上。
设计指导书:STM32系统板配套光盘
四、要求的设计成果
(1)在现有车模的基础上,以嵌入式ARM微处理器构成小车控制核心,同时加装声光电、红外线、超声波传感器、LED显示等外围设备,实现对小车的速度、位置、运行状况的实时测量,并将测量数据传送至处理器进行处理,然后由处理器根据所检测的各种数据实现对电动车的智能控制。
(2)撰写课程设计说明书,要求简洁、通顺,格式规范,设计方案正确,实现技术路线明确,论述内容完整、清楚、规范,数据、资料真实可靠,软件程序运行良好。
(3)要求有完整的电路设计原理图及软件源代码。
五、进程安排
(1)第 1 天:任务布置及相关知识讲解
(2)第2-3天:资料查阅与方案制定
(3)第4-8天:硬件设计、程序编制与调试阶段
(4)第 9 天:撰写设计报告
六、主要参考资料
[1] 田泽. 嵌入式系统开发与应用实验教程. 北京航空航天工业大学出版社,2005.
[2] 郭荣佐,王霖. 《嵌入式系统原理》.北京航空航天大学出版社,.2008.
[3] 周根林.嵌入式系统原理与应用.南京大学出版社, 2006.
[4] 谭浩强. C语言程序设计(第2版).清华大学出版社,2008
[5] 丁峰. ARM系统开发——从实践到提高. 中国电力出版社,2007.
[6] 游雨云. 单片机PWM信号控制智能小车的实现方法.技术与市场, 2009,(12)
[7] 袁新娜,余红英,超声波传感器在智能小车避障系统中的应用. 大众商务教育版(民办教育研究),2009,(8)
指导教师(签名):
20 年 月 日
目 录
1. 总体思想 1
2. 电机驱动 2
2.1 简介 2
2.2 具体实现 2
2.3 功能函数设计 2
3. 遥控系统 6
3.1 遥控器简介 6
3.2 接收探头与解码 7
3.3 红外控制 7
4. 超声波 11
4.1 简介 11
4.2 超声波测距具体实现 11
4.3 超声波程序设计 12
5. 红外寻迹 13
5.1 反射式红外传感器 13
5.2 具体实现方法 14
5.3 寻迹程序设计 14
6. 总结 15
1.总体思想
图 1.1 设计全局图
本次课程设计,我们小组采用stm32作为主控芯片,L298N模块作为电机驱动芯片。在小车车头放置三个反射式红外传感器,由于红外光易于被黑线吸收,利用这个原理,来检测黑线,当检测到黑线时,发射出去的红外光被吸收,红外传感器接受不到反射信号,通过输出信号反馈给STM32,产生中断,作出相应的调整,详细介绍见下文第12页。
车头部分采用一个US-100超声波模块,用于检测前方障碍物,我们小组设置的安全距离为25cm,当小车与前方障碍之间的距离小于25cm时,小车蜂鸣器报警,stm32控制电机,作出相应的调整。关于超声波工作详情,请见下文第11页。
小车尾部安装一枚HS0038红外接收探头,配合一块遥控器,实现遥控小车的功能。
我们小组选用的遥控器编码为NEC协议。红外遥控功能详情,请见下文第7页。
我们在小车的车身上放置一块3.2寸TFT液晶显示器。用于显示时间,车速。车速通过霍尔元件测得。
2.电机驱动
2.1简介
电机运转需要大电流,而stm32驱动能力达不到电机正常运转的要求,故我们小组采用L298N模块驱动电机,L298N拥有4个输入端口,由stm32直接输入,4个输出端,可以驱动两个直流电机。 stm32输出端口的电平变换,可以控制电机的方向。PWM脉宽调制信号,可以控制电机的转速。实现加速减速的功能。
2.2 具体实现
通过stm32的PA0,PA1,根据TIM2产生的不同占空比的PWM波,控制电机的速度,以及正反转。PA3,PA4控制小车前轮,前轮采用舵机控制,在转向方面,不能大幅度转弯,所以,在小车转弯上,我们采用转一段时间,然后倒退一段距离,然后再转,如此反复几次。通过这种方式实现小车的900C转弯。
2.3 功能函数设计
1.void Front()
{
GPIOD->BRR = 0X03;
GPIOA_Conf(); //配置A端口
GPIOA->BRR = 0x0f;
GPIOA->BSRR = 0X01;
}
调用这个函数,实现小车全速向前形式。PD端口的D0,D1位,是控制小车后面两个尾灯。当小车前进时,尾灯关闭。
2.void Back()
{
GPIOD->BSRR = 0x03;
GPIOA_Conf();
GPIOA->BRR = 0x0f;
GPIOA->BSRR = 0X02;
}
调用这个函数,实现小车全速后退。同时开启车身后面的尾灯。
3 . void LeftSlideFront()
{
GPIOD->BSRR = 0X01;
GPIOD->BRR = 0X02;
GPIOA->BRR = 0X04;
GPIOA->BSRR = 0X08;
Time_Configuration(350,0,500,7199);
}
调用此函数,实现小车前进,左转弯。同时开启尾部左边的尾灯,关闭右边的尾灯。
Time_Configuration(350,0,500,7199)为占空比调制函数。通过输入不同的值,改变电机的转速。
4.void Time_Configuration(uint16_t CCR1_Val,uint16_t CCR2_Val,uint16_t periodValue,uint16_t PrescalerValue)
{
/*开启TM2定时器时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/*TIM2定时器复用管脚PA0,PA1,PA2,PA3*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*配置定时器时基*/
TIM_TimeBaseStructure.TIM_Period = periodValue;
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/*配置定时器各通道情况*/
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM2, ENABLE);
TIM_Cmd(TIM2, ENABLE);
}
PWM脉宽调制波形输出,是stm32定时器功能的一大亮点,以往8位单片机输出PWM波形,均为模拟,或者借助外围芯片,而stm32内部定时器,实现了精确的PWM波形直接输出。上面功能函数,为TIM2定时器的配置情况。我在使用时,开启了TIM2定时器的通道1和通道2。分别为PA0,PA1,这两个端口控制小车的后轮电机。由于前轮为舵机。所以,没有采用PWM波形。而是直接给高低电平调整小车的方向。stm32定时器采用预分频处理,即将系统时钟分频后给定时器,这个预分频值,由传入的参数PrescalerValue决定。系统时钟为72MHz,设分频后的频率为F,则:
F = 72MHz/(PrescalerValue+1)
定时器的计数周期为传入参数periodValue的值决定。PWM占空比值由传入参数CCR1_Val和CCR2_Val决定,分别控制PA0,PA1的占空比值。
占空比 = CCR1_Val/periodValue。
4. void LeftSlideBehind()
{
GPIOD->BSRR = 0X01;
GPIOD->BRR = 0X02;
GPIOA->BRR = 0X04;
GPIOA->BSRR = 0X08;
Time_Configuration(0,350,500,7199);
}
调用此函数,控制小车后退并左转弯。同时开启左边尾灯,关闭右边尾灯。
5.void RightSlideFront()
{
GPIOD->BSRR = 0X02;
GPIOD->BRR = 0X01;
GPIOA->BRR = 0X08;
GPIOA->BSRR = 0x04;
Time_Configuration(350,0,500,7199);
}
调用此函数,控制小车前进并右转弯。同时关闭左边尾灯,开启右边尾灯。
6. void RightSlideBehind() //后退,右转弯
{
GPIOD->BSRR = 0X02;
GPIOD->BRR = 0X01;
GPIOA->BRR = 0X08;
GPIOA->BSRR = 0X04;
Time_Configuration(0,350,500,7199);
}
调用此函数,控制小车后退并右转弯。同时关闭左边尾灯,开启右边尾灯。
7. void Upshift()
{
uint16_t i;
GPIOD->BRR = 0x03;
for(i = 100;i <= 180;i = i + 10)
{
Delay(200);
Time_Configuration(i,0,500,7199);
}
while(i <= 500)
{
i = i + 50;
Time_Configuration(i,0,500,7199);
Delay(100);
}
}
调用此函数,实现小车的加速,我们小组将加速过程分为2级,第一级为慢加速,让速度慢慢起来,第二级加速为快加速,当速度达到一定值后,占空比增大的幅度加强。
8. void SlowDown()
{
uint16_t i = 400;
GPIOD->BSRR = 0X03;
while(i > 200)
{
Time_Configuration(i,0,500,7199);
i = i-50;
Delay(70);
}
for(;i > 170; i = i - 5)
{
Time_Configuration(i,0,500,7199);
Delay(80);
}
}
调用此函数,实现小车的减速,减速过程,我们也分为两级。第一级为快速减速,第二级为慢速减速。使小车平稳减速。
9.void Brake()
{
GPIOD->BSRR = 0x03;
GPIOA_Conf();
GPIOA->BSRR = 0x0f;
}
调用该函数,小车将停止。同时后面尾灯开启。
3.遥控系统
3.1 遥控器简介
我们小组使用的遥控器发射编码为NEC协议, NEC编码协议中,遥控器每发送一个8位数据,可以分为5个部分:
图 3.1 NEC协议编码规则
当按下遥控器上的任意一个键时,遥控器将发送一个38KHz的载波信号,根据NEC编码协议,如果发送数据位为1,则向外发送38KHz的载波信号,持续发送0.56ms.然后停止发送1.685ms后继续发送下一位。如果发送数据位为0,则红外遥控向外发送38KHz的载波信号,持续发送0.56ms,然后停止发送0.565ms后继续发送下一位。
3.2 接收探头与解码
接受红外信号部分,我们采用HS0038接收探头,HS0038共三个引脚,分别为,OUT、VCC、GND。通电后,当没有收到红外信号时,OUT端口默认为高电平。接受端口信号与红外遥控发送信号电平相反。
在解码方面,接收探头接受到38KHz的载波后,输出端OUT电平拉低。由于NEC发射编码中,采用的是38KHz载波表示高,无发射表示低。所以在接受探头部分的电平高低,与发射部分刚好相反。解码部分,数据1,0的电平宽度为别是:
图 3.2 NEC协议1、0电平宽度
由于每个数据位开始低电平均为0.56ms,所以,我们使用TIM3定时器,准确捕获到每位数据高电平持续时间。通过捕获到的值,来确认1和0.
通过软件解码时,首先接受到引导码,9ms的低电平和4.5ms的高电平,然后是地址码和地址反码,最后是数据码和数据反码。在程序设计上,我们定义个unsigned char型数组,分别记录下地址码、地址反码、数据码、数据反码。取出数组下标为2和3的值,将下标为3的数组数据取反,判断是否相等,如果不相等,表示解码数据有误;如果相等,表示解码正确。
3.3 红外控制
将stm32的外部中断3端口与红外探头的输出端相连,捕捉红外遥控发射来的信号。外部中断端口程序配置如下:
1.void EXTI3_Configration()
{
/***************配置PC3端口,作为外部中断触发端口***********/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOC, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource3);
/****************外部中断线配置,设置为上升沿触发****************/
EXTI_InitStructure.EXTI_Line = EXTI_Line3;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/********************中断向量表配置*****************/
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
配置好外部中断后,当stm32上电后,便会实时监控PC3端口,当接受到红外信号后,便产生一个中断信号,调用中断处理函数,处理该事件,下面为中断处理函数,主要是解码红外信号:
2.void EXTI3_IRQHandler(void)
{
int i,j,Counter = 0;
char IR[4] = {0};
char ch1=0,ch2=0;
if(EXTI_GetITStatus(EXTI_Line3) != RESET)
{
TIM3->CNT = 0;
TIM_Cmd(TIM3,ENABLE);
while(TIM_GetCounter(TIM3) < 7000);
TIM_Cmd(TIM3,DISABLE);
TIM3->CNT = 0;
if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3) == 0)
{
while(!GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3));
TIM3->CNT = 0;
TIM_Cmd(TIM3,ENABLE);
while(TIM_GetCounter(TIM3) < 3500);
TIM_Cmd(TIM3,DISABLE);
if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3) == 1)
{
while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3));
for(i = 0; i< 4; i++)
{
for(j = 0; j < 8; j++)
{
while(!GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3));
TIM3->CNT = 0;
TIM_Cmd(TIM3,ENABLE);
while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3));
Counter = TIM_GetCounter(TIM3);
TIM_Cmd(TIM3,DISABLE);
ch1 = ch1>>1;
if(Counter > 840)
{
ch1 = ch1|0x80;
}
else
{
ch1 = ch1|0;
}
Counter = 0;
}
IR[i] = ch1;
}
ch1 = IR[2];
ch2 = IR[3];
ch2 = ~ch2;
if(ch1 == ch2)
{
switch(ch1)
{
case 0x07:LeftSlideFront();break;
case 0x09:RightSlideFront();break;
case 0x40:Front();break;
case 0x19:Back();break;
case 0x16:LeftSlideBehind();break;
case 0x0d:RightSlideBehind();break;
case 0x0c:Upshift();break;
case 0x5e:SlowDown();break;
case 0x15:Brake();break;
default :Brake();break;
}
}
}
}
Delay(500);
EXTI_ClearITPendingBit(EXTI_Line3);
}
}
这个函数为中断处理函数,在中断处理函数中,我们又用到了一个TIM3定时器,该定时器主要是解码红外信号,根据上文所述的0,1编码规则,用TIM3定时器,所捕获到的值,来判断信号0,1,实现软件解码红外信号。下面为TIM3定时器的配置:
3. void TIM3_Configuration()
{
TIM_DeInit(TIM3);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
TIM_TimeBaseStructure.TIM_Period = 50000;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
TIM_PrescalerConfig(TIM3,71,TIM_PSCReloadMode_Immediate);
TIM_ARRPreloadConfig(TIM3,DISABLE);
TIM_Cmd(TIM3,DISABLE);
}
设置预分频值为71,经过分频后,计数器的频率为1MHz。周期为50000.计数方式为向上计数。虽然stm32普通定时器的时钟为36MHz,如果将TIM_ClockDivision的值设置为0,则采用预分频时,时钟值应选72MHz进行分频。
4.超声波
4.1 简介
通过超声波发射装置发出超声波,根据接收器接到超声波时的时间差就可以知道距离了。超声波发射器向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。(超声波在空气中的传播速度为340m/s,根据计数器记录的时间t,就可以计算出发射点距障碍物的距离(s),即:s=340t/2)
4.2 超声波测距具体实现
我们在小车的前端放置一个超声波模块,采用查询法,每隔1s,发射一个10us以上的脉冲信号,超声波模块便自动发送8个40Khz的信号。当模块接收到返回信号时,输出端会输出一个高电平,这个高电平的持续时间,就是超声波模块到达障碍物,声速的来回时间。如果测得前方障碍物距离小于设置距离,则小车后退,并发出报警蜂鸣声。
4.3 超声波程序设计
1. float Distance()
{
float distance;
int time;
TIM3->CNT = 0; //非常重要,不清零,没结果
GPIOB->BSRR = 0X01;
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0);//等待接收到反回信号
GPIOB->BRR = 0X01;
TIM_Cmd(TIM3,ENABLE); //开启定时器,记下电平持续时间
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 1);
TIM_Cmd(TIM3,DISABLE);
time = TIM_GetCounter(TIM3);
distance = (float)time*0.017; //cm数量级
return distance;
}
程序中的TIM3定时器,在上文3.3.3已经详细的描述。我们将stm32的PB0作为发送10us以上高电平的端口,将PB1作为接受超声波模块馈送的时间信号电平端口。该高电平的时间,为超声波来回障碍物的时间。该函数返回值,即为小车到障碍物的距离。
2. void KeepDistance() //超声波测距,距离控制函数
{
GPIOB->BRR = 0x100;
if(Distance() < 25.0)
{
GPIOB->BSRR = 0x100;
RightSlideBehind();
Delay(200);
GPIOB->BRR = 0x100;
Delay(700);
GPIOA->BSRR = 0x0c;
Time_Configuration(70,0,100,71);
}
}
调用这个函数,当小车查询到前方距离小于25cm时,便进行一些列的调整,如蜂鸣器想起,小车向右后转。
5.红外寻迹
5.1 反射式红外传感器
图5.1 反射式红外传感器
如图5.1所示,当红外发射管发射信号,经地面反射到接收管时,接收管部位电阻值很小;当红外传感器与地面距离拉大,接收管接收不到反射信号时,接收管部位电阻值很大。采用一个电压比较器LM393,LM393为两端输入,一端输出,比较两个输入信号的大小。我们将红外传感器接收管在接收到信号和没有接收到信号时,电阻两端的电压与一个固定的值相比,接收到信号时,LM393输出低电平;没有接受到信号时,LM393输出高电平。通过高低电平,判断红外管发出的信号是否被黑线吸收。
5.2 具体实现方法
小车上的黑线检测设备,采用的中断触发方式是,下降沿。由于电机在转动过程中,不可避免的会发生突然变向,减速等。这样会干扰电源电压,由于我我们组采用的stm32为3.3V供电,该电压有6个电池串联,经过稳压芯片稳压后,输出3.3V给stm32,当点击由于突然变向,加速减速才生大电流,对电池电压产生较大的冲击,稳压芯片输出截止。黑线检测的模块与stm32并联,当稳压芯片输出的3.3V电压突然截止时,寻迹模块输出电压为0.如果采用下降沿触发,这时,由于电压的不稳定而导致了一个有害的触发中断。
通过修改硬件电路,采用上升沿触发,当红外对管检测到黑线时,输出信号为0,当小车没有检测到黑线时,输出信号为1。当稳压芯片突然截止时,输出也0,这样可以有效的解决电机对寻迹模块的干扰。
我们小组采用3个寻迹模块,stm32采用3个外部触发端口分别与3个寻迹模块相连。左右两边寻迹模块用于检测跑到边沿,防止小车冲出跑到。中间寻迹模块用于检测小车转弯线。stm32分枪占式优先级和响应式优先级。如果抢占式优先级相同,则不能发生中断嵌套。小车经过转弯线时,三个寻迹模块均会检测到黑线。所以,我们设置中间寻迹模块的抢占式优先级最高,两边抢占式等级低于中间,当小车经过转弯线时,三个中断同时,或一次来临。中间中断等级打断两边,保证中间的中断执行程序能顺利执行。
5.3 寻迹程序设计
我们采用三个外部中断,分别为PC0,PC1,PC3三个端口,分别监控三个寻迹模块。下面以外部中断0为例:
1.void EXTI0_Configration()
{
/************配置PC0端口,作为外部中断触发端口*******/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOC, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource0);
/****************外部中断线配置,设置为下降沿触发****************/
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/********************中断向量表配置*****************/
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0f;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
将外部中断设置为上升沿触发,出现中断后,按照中断处理函数进行,下面为中断处理函数:
2.void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{ EXTI_ClearITPendingBit(EXTI_Line0);
Back();
Delay(5);
RightSlideBehind();
Delay(1000);
GPIOA->BSRR = 0X0C;
Time_Configuration(350,0,500,7199);
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
其余两个中断按照类似的方法配置。端口号改为PC1,PC2。
6.总结
由于超声波模块使用的频率是40KHz,红外遥控使用的是38KHz频率。在小车运行过程中,会产生冲突。即遥控器发送的信号会干扰超声波对距离的判断,考虑到黑色的纸可以较好的吸收红外信号,为了减小干扰。我们在小车的车上,靠近超声波模块的地方,贴上了黑色纸张。减小红外信号对超声波模块的干扰。测试证明,效果很明显。基本解决了遥控器发射的红外信号对超声波的干扰。
小车与TFT模块,霍尔测速上的通信。通过SPI接口,实现STM32与STC89C52的通信。把霍尔元件测得的车速,超声波模块测得的距离实时传送到STC89C52控制的TFT显示器上。实现测量数据的可视化,直观化。
主函数为:
int main()
{
RCC_Config();
GPIO_Configuration();
GPIOB->BRR = 0x100; //初始化蜂鸣器--关闭
GPIOD->BRR = 0X03; //关掉尾灯
Delay_ms(1000); //消除上电时,脉冲导致的莫名其妙的中断操作。
/***4个外部中断*****/
EXTI0_Configration(); //左边黑线检测
EXTI1_Configration(); //中间黑线检测
EXTI2_Configration(); //右边黑线检测
EXTI3_Configration(); //红外控制端口
TIM3_Configuration(); //定时器配置,用于超声波测距
while(1)
{
KeepDistance();
Delay(100); //控制采样时间。
}
展开阅读全文