嵌入式小车实验报告.docx |
您所在的位置:网站首页 › 嵌入式触摸屏实验报告 › 嵌入式小车实验报告.docx |
嵌入式小车实验报告.docx 《嵌入式小车实验报告.docx》由会员分享,可在线阅读,更多相关《嵌入式小车实验报告.docx(21页珍藏版)》请在冰豆网上搜索。 嵌入式小车实验报告 嵌入式系统实验报告 一、实验目的 1.熟悉Keil集成开发环境的使用 2.熟悉STM32F107v实验板 3.掌握相关中断设计技巧 4.熟练运用ADC转换 二、实验要求 1.小车速度控制 实现小车速度的控制,能够根据小车当前的运动状态对小车的速度快慢进行调节。 2.小车方向控制 车辆的方向控制,不对转向角度提出要求;能够在运行过程中,需要根据具体的路况对自身运行状态进行相应的控制,能够进行以下四种状态的切换: 前进: 四个车轮能够同时朝着前进的方向进行运动,保证速度一致; 后退: 四个车轮能够同时朝着后退的方向进行运动,保证速度一致; 左转: 左边的两个轮子后退,而右边的两个轮子前进。 右转: 右边的两个轮子后退,而左边的两个轮子前进。 3.串口控制要求 能够使用串口功能,实现小车的远程控制,最好是采用无线通信接口进行控制,能够将小车的所有功能实现 三、实验原理 1.硬件配置 该实验利用L298N电机驱动芯片作为开发板与电机的连接件。 L298N是ST公司生产的一种高电压、大电流电机驱动芯片。 该芯片采用15脚封装。 主要特点是: 工作电压高,最高工作电压可达46V;输出电流大,瞬间峰值电流可达3A,持续工作电流为2A;额定功率25W。 内含两个H桥的高电压大电流全桥式驱动器,可以用来驱动直流电动机和步进电动机、继电器线圈等感性负载;采用标准逻辑电平信号控制;具有两个使能控制端,在不受输入信号影响的情况下允许或禁止器件工作有一个逻辑电源输入端,使内部逻辑电路部分在低电压下工作;可以外接检测电阻,将变化量反馈给控制电路。 使用L298N芯片驱动电机,该芯片可以驱动一台两相步进电机或四相步进电机,也可以驱动两台直流电机。 简要说明: ●工作电压: 控制信号直流5V;电机电压直流3V~46V(建议使用36伏以下) ●最大工作电流: 2.5A ●额定功率: 25W ●特点: 1、具有信号指示2、转速可调3、抗干扰能力强4、具有过电压和过电流保护5、可单独控制两台直流电机6、可单独控制一台步进电机7、PWM脉宽平滑调速8、可实现正反转 2.产生PWM波以及TIM定时器的设置 为获取PWM波我们首先对TIM进行设置,由于TIM是可编程的定时器,则可以认为是脉宽可调的波形。 这里使用通用定时器TIM3,令系统内部时钟为TIM时钟源,则TIM初始频率为72MHz,调整计数溢出大小,使计数器每计7200个产生一个更新事件(即TIM_Period=7200),这样可以产生PWM的输出频率为10KHz,该速度可以使电机匀速平滑工作。 占空比——通过调节方波的开通时间Ton,从而调节平均电压: (V) 其中: E——电源电压;T——矩形波周期; 3.基于ADC转换的速度控制方案 3.1.STM32ADC简介 Ø12位ADC是一个连续近似模拟到数字的转换器。 它由18个多路复用通道,从而允许它测量来自16个外部和2个内部源的信号。 不同通道的A/D转换可以在单一,连续,扫描或者间断模式下进行。 ADC转换的结果保存在左对齐或者右对齐的16位数据寄存器中。 Ø主要有如下特性: ●12位精度 ●转换结束时,注入转化结束时,模拟看门狗事件发生时都会产生中断 ●单一和连续转换模式 ●扫描模式,通道0到通道n的自动转化 ●自校准 ●数据对齐方式与内建数据一致 ●按通道配置采样时间 ●规则和注入转化模式都支持外部触发选项 ●间断模式 ●双工模式(在带2个ADC的设备上) 3.2.ADC控制速度原理 使用ADC1和DMA连续地把ADC1的转换数据从ADC1传输到存储空间。 ADC1被配置成从ADC的14号通道连续地转换数据。 每次结束一次ADC转换后触发一次DMA传输,在DMA循环模式中,持续地把ADC1的DR数据寄存器的数据传输到ADC_ConvertedValue变量。 然后通过LCD显示出来。 并且ADC_ConvertedValue的值是我们速度控制的标准,ADC_ConvertedValue得到后调用Speed()函数,以此来控制小车的速度。 这样,当我们旋转RV1可调电阻便会产生0-5V的电压,相应的ADC_ConvertedValue的值也为0-5,这样通过调用Speed()函数,我们得到0-5不同等级的速度,实现无极调速。 ADC各个参数配置意义如下: ADC_Mode ADC配置成独立模式或者双模式 ADC_ScanConvMode 指定ADC执行在多通道或单通道模式 ADC_ContinuousConvMode 指定转换是连续执行还是单次执行 ADC_ExternalTrigConv 触发ADC转换的触发源 ADC_DataAlign ADC数据对齐方式 ADC_NbrOfChannel 被转换的ADC的通道数 3.3.程序设计及实现 Ø配置DMA /*DMA1channel1configuration----------------------------------------------*/ DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr=ADC1_DR_Address; DMA_InitStructure.DMA_MemoryBaseAddr=(uint32_t)&ADCConvertedValue; DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize=1; DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode=DMA_Mode_Circular; DMA_InitStructure.DMA_Priority=DMA_Priority_High; DMA_InitStructure.DMA_M2M=DMA_M2M_Disable; DMA_Init(DMA1_Channel1,&DMA_InitStructure); /*EnableDMA1channel1*/ DMA_Cmd(DMA1_Channel1,ENABLE); Ø配置ADC1 /*ADC1configuration------------------------------------------------------*/ ADC_InitStructure.ADC_Mode=ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode=ENABLE; ADC_InitStructure.ADC_ContinuousConvMode=ENABLE; ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel=1; ADC_Init(ADC1,&ADC_InitStructure); /*ADC1regularchannel14configuration*/ ADC_RegularChannelConfig(ADC1,ADC_Channel_14,1,ADC_SampleTime_55Cycles5); /*EnableADC1DMA*/ ADC_DMACmd(ADC1,ENABLE); /*EnableADC1*/ ADC_Cmd(ADC1,ENABLE); /*EnableADC1resetcalibarationregister*/ ADC_ResetCalibration(ADC1); /*ChecktheendofADC1resetcalibrationregister*/ while(ADC_GetResetCalibrationStatus(ADC1)); /*StartADC1calibaration*/ ADC_StartCalibration(ADC1); /*ChecktheendofADC1calibration*/ while(ADC_GetCalibrationStatus(ADC1)); /*StartADC1SoftwareConversion*/ ADC_SoftwareStartConvCmd(ADC1,ENABLE); Ø用ADC转换的数据实现无级调速 while (1) { printf("ADCrusult: %3.2fV\r",(float)(ADCConvertedValue)/0xfff*5); //将ADCConvertedValue的值转换成十进制数 Speed((float)(ADCConvertedValue)/0xfff*5);//转换成速度输出 4.基于EXTI外部中断的方向控制 4.1.EXTI外部中断控制方向原理 在这个实验中我们主要用中断来实现小车的方向控制。 用KEY和TAMPER两个按键实现小车的四个方向控制。 通过编写KEY和TAMPER的中断服务程序,修改车的运行方向。 这里我们定义两个布尔型变量m,n来代表按键的状态,m=1表示KEY按键按下,m=0表示KEY按键没有按下,或者按下状态被清除,n=1表示TAMPER按键按下,n=0表示TAMPER按键没有按下,或者按下状态被清除 实现: ●当KEY和TAMPER键都没被按下时,小车实现“前进”状态; ●当KEY键按下,TAMPER键没按下时,小车实现“左转”状态; ●当KEY键没按下,TAMPER键按下时,小车实现“右转”状态; ●当KEY和TAMPER键都按下时,小车实现“后退”状态; 4.2.程序设计及实现 Ø中断服务程序如下: voidEXTI15_10_IRQHandler(void)//TAMPER按键的中断配置 { if(EXTI_GetITStatus(TAMPER_BUTTON_EXTI_LINE)! =RESET) { /*ToggleLED1*/ //printf("ExternalINToccur! \n");//按下KEY按键时,再在屏幕上显示ExternalINToccur n=! n;//在中断服务程序中将n取反 /*CleartheKeyButtonEXTIlinependingbit*/ EXTI_ClearITPendingBit(TAMPER_BUTTON_EXTI_LINE); } } voidEXTI9_5_IRQHandler(void)///KEY按键中断配置 { if(EXTI_GetITStatus(KEY_BUTTON_EXTI_LINE)! =RESET) { /*ToggleLED1*/ //printf("ExternalINToccur! \n");//按下KEY按键时,再在屏幕上显示ExternalINToccur m=! m;//在中断服务程序中将m取反 /*CleartheKeyButtonEXTIlinependingbit*/ EXTI_ClearITPendingBit(KEY_BUTTON_EXTI_LINE); } } Ø主函数部分如下: STM_EVAL_PBInit(Button_KEY,Mode_EXTI); STM_EVAL_PBInit(Button_TAMPER,Mode_EXTI); EXTI_GenerateSWInterrupt(KEY_BUTTON_EXTI_LINE); EXTI_GenerateSWInterrupt(TAMPER_BUTTON_EXTI_LINE); while (1) { printf("ADCrusult: %3.2fV\r",(float)(ADCConvertedValue)/0xfff*5); Speed((float)(ADCConvertedValue)/0xfff*5); if(m==FALSE&&n==FALSE)//当KEY和TAMPER键都没被按下时,小车实现“前进”状态; { Direction('f'); } if(m==TRUE&&n==FALSE) {Direction('l');//当KEY键按下,TAMPER键没按下时,小车实现“左转”状态; } if(m==FALSE&&n==TRUE) { Direction('r');//当KEY键没按下,TAMPER键按下时,小车实现“右转”状态; } if(m==TRUE&&n==TRUE) { Direction('b');//当KEY和TAMPER键都按下时,小车实现“后退”状态; } } } 5.基于USART的串口通讯设计 Ø/*USART1配置*/ USART_InitStructure.USART_BaudRate=9600;//波特率为9600 USART_InitStructure.USART_WordLength=USART_WordLength_8b;//每次接收数据为8位。 USART_InitStructure.USART_StopBits=USART_StopBits_1;//停止位为1位 USART_InitStructure.USART_Parity=USART_Parity_No;//不需要校正 USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx; /*初始化USART1*/ USART_Init(USARTy,&USART_InitStructure); /*中断使能接收USART1*/ USART_ITConfig(USARTy,USART_IT_RXNE,ENABLE); /*使能接收USART1*/ USART_Cmd(USARTy,ENABLE); Ø中断接收控制(只需要接收数据) voidUSARTy_IRQHandler(void) { if(USART_GetITStatus(USARTy,USART_IT_RXNE)! =RESET) { /*接收数据*/ RxBuffer1[RxCounter1++]=USART_ReceiveData(USARTy); if(RxCounter1==NbrOfDataToRead1) { /*DisabletheUSARTyReceiveinterrupt*/ USART_ITConfig(USARTy,USART_IT_RXNE,DISABLE); } } } Ø数据处理函数 switch(direction_flag) { case0: Direction('f');break;//控制程序 case1: Direction('b');break; case2: Direction('l');break; case3: Direction('r');break; default: Direction('f');break; } 6.实验程序(部分解释在实验报告前面) 1)定义部分 #include"stm32f10x.h" #include"stm3210c_eval_lcd.h" #include"stm32_eval.h" #include #include"stm32f10x_tim.h" #include #include #include"stm32f10x_dma.h" #include"stm32f10x_adc.h" #defineADC1_DR_Address((uint32_t)0x4001244C) /*Privatemacro-------------------------------------------------------------*/ /*Privatevariables---------------------------------------------------------*/ ADC_InitTypeDefADC_InitStructure; DMA_InitTypeDefDMA_InitStructure; __IOuint16_tADCConvertedValue; ErrorStatusHSEStartUpStatus; voidRCC_cfg(void); voidGPIO_cfg(void); voidTIMER_cfg(void); voidPWM_cfg(void); boolm=FALSE; booln=FALSE; voidForward(void); voidBackward(void); voidLeft_turn(u8); voidRight_turn(u8); voidStop(void); externintdutyfactor1=1; externintdutyfactor2=1; externintdutyfactor3=1; externintdutyfactor4=1; externintspeed_1=0; externcharmotor='f'; externvoidSpeed(floats); externvoidDirection(chard); 2)时钟配置 voidRCC_cfg() { SystemInit(); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD |RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE); /*Enableperipheralclocks--------------------------------------------------*/ /*EnableDMA1clock*/ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE); /*EnableADC1andGPIOCclock*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE); } 3)GPIO配置 voidGPIO_cfg() { GPIO_InitTypeDefGPIO_InitStructure; GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_Init(GPIOC,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_12|GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOC,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN; GPIO_Init(GPIOC,&GPIO_InitStructure); } 注: 由于电机原来有个输出拐角与ADC转换输出拐角重复,都为GPIO_Pin_4,因此在这里我们将电机输出改为GPIO_Pin_12 4)TIM配置 voidTIMER_cfg() { TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure; TIM_DeInit(TIM3);//重新将Timer设置为缺省值 TIM_InternalClockConfig(TIM3);//采用内部时钟给TIM3提供时钟源 TIM_TimeBaseStructure.TIM_Prescaler=0;//预分频系数为0,即不进行预分频,此时TIMER的频率为72MHz TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;//设置时钟分割 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//设置计数器模式为向上计数模式 TIM_TimeBaseStructure.TIM_Period=7200-1;//设置计 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |