机械工程与自动化学院《嵌入式小车实验》实验
报告
软件系统测试报告下载sgs报告如何下载关于路面塌陷情况报告535n,sgs报告怎么下载竣工报告下载
嵌入式小车实验实验报告
一、实验功能介绍
本实验采用ARM7系列的EasyARM2131作为智能小车的检测和控制核心。我们使用步进电机作为小车的马达,通过调整PWM输出的占空比控制步进电机。引脚P0.0、P0.1输出两路PWM信号来控制两个电机的转动、停止,及转动速度大小和方向,通过调整PWM输出的占空比当PWM输出图(1)的波形时,电机停止;当PWM输出图(2)的波形时,电机全速顺时针转动;当PWM输出图(3)的波形时,电机全速逆时针转动;当PWM的占空比发生变化时,实现电机的速度发生大小改变,PWM的波形如图(4)。综上所述:实现了电机的驱动,分别使用了ARM上的P0.0、P0.1作为PWM的输出控制两个电机的正反转和转速,通过ARM上的key1、key2、key3、key4、key5按钮来控制两路PWM信号的输出波形占空比,从而实现小车停止、前进,后退,左转,右转等功能。
图(1)
图(2)
图(3)
图(4)
同时,LED灯进行流水灯,每按一下按键蜂鸣器发一声。
控制流程:key1控制小车前进,按两下key1,加速前进;key2控制小车倒退,按两下,加速倒退;key3控制小车左转;key4控制小车右转;key5控制小车停止。
二、嵌入式小车实验图片
下图为给ARM下载程序时:
下图为小车运行时正面:
下图为小车运行时背面:
三、程序代码
PWM程序:
#include "../user/includes.h"
#define PWM_TC_EN 1
#define PWM_RST 2
#define PWM_EN 8
#define PWM_VAL_LIST_SIZE 5
const u32 pwm_mr_val[PWM_VAL_LIST_SIZE] = {PWMMR_VAL_0, PWMMR_VAL_1, PWMMR_VAL_2, PWMMR_VAL_3, PWMMR_VAL_4};
#define PWM_VAL_PTR_ORG 2 //初始化时指向pwm_mr_val的第2项,开始时输出1500微秒
#define PWM_VAL_PTR_TRE 3
#define PWM_VAL_PTR_ONE 1
u8 g_pwm_val_left_ptr = PWM_VAL_PTR_ORG;
u8 g_pwm_val_right_ptr = PWM_VAL_PTR_ORG;
void pwm_init(void)
{
//设置P0.0,P0.1为PWM1与PWM3输出引脚
PINSEL0 &= 0xFFFFFFF0;
PINSEL0 |= 0x0000000A;
g_pwm_val_left_ptr = PWM_VAL_PTR_ORG;
g_pwm_val_right_ptr = PWM_VAL_PTR_ORG;
PWMTCR = PWM_RST;
PWMPR = 0;
PWMPCR = 0;
PWMLER = 0; //不锁存
PWMMR0 = PWMMR0_VAL;
//设置PWM的周期为20ms
PWMMR1 = pwm_mr_val[g_pwm_val_left_ptr];
PWMMR3 = pwm_mr_val[g_pwm_val_right_ptr];
PWMLER = (PWM0 | PWM1 | PWM3);
PWMMCR = 2; //匹配后复位
PWMPCR = (PWM1 | PWM3) << 8; //设置PWM1和PWM3有效
PWMTCR = PWM_TC_EN | PWM_EN; //PWM_TC_EN为开始计数,PWM_EN为整个PWM输出的使能开关
}
void pwm_acc(u8 pwm)
{
if(pwm & PWM1)
{
if(g_pwm_val_left_ptr + 1 < PWM_VAL_LIST_SIZE)
{
g_pwm_val_left_ptr ++;
PWMLER &= ~PWM1;
PWMMR1 = pwm_mr_val[g_pwm_val_left_ptr];
PWMLER |= PWM1;
}
}
if(pwm & PWM3)
{
if(g_pwm_val_right_ptr + 1 < PWM_VAL_LIST_SIZE)
{
g_pwm_val_right_ptr ++;
PWMLER &= ~PWM3;
PWMMR3 = pwm_mr_val[g_pwm_val_right_ptr];
PWMLER |= PWM3;
}
}
}
void pwm_dec(u8 pwm)
{
if(pwm & PWM1)
{
if(g_pwm_val_left_ptr > 0)
{
g_pwm_val_left_ptr --;
PWMLER &= ~PWM1;
PWMMR1 = pwm_mr_val[g_pwm_val_left_ptr];
PWMLER |= PWM1;
}
}
if(pwm & PWM3)
{
if(g_pwm_val_right_ptr > 0)
{
g_pwm_val_right_ptr --;
PWMLER &= ~PWM3;
PWMMR3 = pwm_mr_val[g_pwm_val_right_ptr];
PWMLER |= PWM3;
}
}
}
void pwm_rig(void)
{
g_pwm_val_right_ptr = PWM_VAL_PTR_ORG;
g_pwm_val_left_ptr = PWM_VAL_PTR_TRE;
PWMLER &= (~(PWM1 | PWM3));
PWMMR1 = pwm_mr_val[g_pwm_val_left_ptr];
PWMMR3 = pwm_mr_val[g_pwm_val_right_ptr];
PWMLER |= (PWM1 | PWM3);
}
void pwm_lef(void)
{
g_pwm_val_right_ptr = PWM_VAL_PTR_ONE;
g_pwm_val_left_ptr = PWM_VAL_PTR_ORG;
PWMLER &= (~(PWM1 | PWM3));
PWMMR1 = pwm_mr_val[g_pwm_val_left_ptr];
PWMMR3 = pwm_mr_val[g_pwm_val_right_ptr];
PWMLER |= (PWM1 | PWM3);
}
void pwm_rst(void)
{
g_pwm_val_left_ptr = PWM_VAL_PTR_ORG;
g_pwm_val_right_ptr = PWM_VAL_PTR_ORG;
PWMLER &= (~(PWM1 | PWM3));
PWMMR1 = pwm_mr_val[g_pwm_val_left_ptr];
PWMMR3 = pwm_mr_val[g_pwm_val_right_ptr];
PWMLER |= (PWM1 | PWM3);
}
按键程序:
#include "../user/includes.h"
#include "../gpio/gpio.h"
#include "../user/truck.h"
//按键的优先级最低,设为0,但频率最高
xTaskHandle g_key_handle = (void*)0;
extern xSemaphoreHandle g_sem_handle;
u32 key_get(void) //读GPIO
{
u32 key = 0;
gpio_read_group(KEY_GROUP, &key);
return key;
}
void key_tsk(void* p_para) //按键的任务函数
{
u32 key = 0;
static u32 last_key = 0;
static u8 i = 0;
while(1)
{
key = key_get();
if(last_key != key)
{
last_key = key;
i = 0;
}
else
{
if(i < 255)
{
i ++;
}
}
if(i == KEY_RETRY_TIMES) //KEY_RETRY_TIMES为3,连读3次,以确认按键有效
{
if((key & KEY_LEFT_FORWARD) ==0)
{
xSemaphoreGive(g_sem_handle); //按键任务抛出信号量,以便和蜂鸣器同步,让蜂鸣器鸣叫
truck_left_acc();
truck_right_acc();
vTaskDelay(KEY_TSK_KEY_DLY);
}
else if((key & KEY_RIGHT_FORWARD) == 0)
{
xSemaphoreGive(g_sem_handle);
truck_rig();
vTaskDelay(KEY_TSK_KEY_DLY);
}
else if((key & KEY_LEFT_BACKWORD) == 0)
{
xSemaphoreGive(g_sem_handle);
truck_left_dec();
truck_right_dec();
vTaskDelay(KEY_TSK_KEY_DLY);
}
else if((key & KEY_RIGHT_BACKWORD) == 0)
{
xSemaphoreGive(g_sem_handle);
truck_lef();
vTaskDelay(KEY_TSK_KEY_DLY);
}
else if((key & KEY_STOP) == 0)
{
xSemaphoreGive(g_sem_handle);
truck_stop();
vTaskDelay(KEY_TSK_KEY_DLY);
}
//vTaskDelay(KEY_TSK_KEY_DLY);
}
vTaskDelay(KEY_TSK_DLY_TICK); //查一次按键就挂起按键任务KEY_TSK_DLY_TICK个系统心跳节拍
}
}
t_rtn key_init(void)
{
gpio_set_pin_as_io(KEY_GROUP, KEY_PIN);
gpio_set_input(KEY_GROUP, KEY_PIN);
if(xTaskCreate(key_tsk, KEY_TSK_NAME, KEY_TSK_STK_SIZE, INVALID_PTR, KEY_TSK_PRI, &g_key_handle) == pdTRUE)
//创建按键的任务函数
{
return NO_ERR;
}
else
{
return TASK_CREATE_FAIL;
}
}
主程序:
#include "includes.h"
//#include "../gpio/gpio.h"
#include "../led/led.h"
#include "../key/key.h"
#include "../beep/beep.h"
#include "../pwm/pwm.h"
#include "truck.h"
xSemaphoreHandle g_sem_handle = (void*)0; //声明信号量,用于按键与蜂鸣器同步
s32 main(void)
{
vSemaphoreCreateBinary(g_sem_handle); //创建信号量,g_sem_handle默认为1,多任务启动时蜂鸣器会鸣叫
led_init(); //初始化跑马灯,并创建任务
beep_init(); //蜂鸣器任务
key_init(); //按键任务
truck_init(); //PWM设置
vTaskStartScheduler(); //任务调度函数
while(1)
{
}
}
其中truck程序:
#include "typedef.h"
#include "usercfg.h"
#include "../pwm/pwm.h"
void truck_init(void)
{
pwm_init();
}
void truck_left_acc(void)
{
pwm_acc(PWM_LEFT);
}
void truck_right_acc(void)
{
pwm_dec(PWM_RIGHT);
}
void truck_left_dec(void)
{
pwm_dec(PWM_LEFT);
}
void truck_right_dec(void)
{
pwm_acc(PWM_RIGHT);
}
void truck_rig(void)
{
pwm_rig();
}
void truck_lef(void)
{
pwm_lef();
}
void truck_stop(void)
{
pwm_rst();
}
Led灯程序:
xTaskHandle g_led_handle = (void*)0;
void led_run(void)
{
static u32 led = 0;
gpio_write_group(LED_GROUP, 1 << (led + 18));
led ++;
if(led >= MAX_LED_NUM)
{
led = 0;
}
}
void led_tsk(void* p_dly_ms) //走马灯任务函数
{
while(1) //一个任务就是一个死循环,循环熄灭LED
{
led_run();
vTaskDelay(configTICK_RATE_HZ * LED_TSK_DLY_MS / 1000); //此函数使走马灯任务挂起
}
}
t_rtn led_init(void)
{
gpio_set_pin_as_io(LED_GROUP, LED_PINS);
gpio_set_output(LED_GROUP, LED_PINS);
gpio_set(LED_GROUP, LED_PINS);
if(xTaskCreate(led_tsk, //led_tsk为任务函数入口地址
LED_TSK_NAME, //为任务名
LED_TSK_STK_SIZE, //为任务堆栈空间
INVALID_PTR, //为空指针,即不给任务函数传递参数
LED_TSK_PRI, //为任务优先级
&g_led_handle) == pdTRUE)
//走马灯任务创建函数,g_led_handle为任务句柄
{
return NO_ERR;
}
else
{
return TASK_CREATE_FAIL;
}
}
蜂鸣器程序:
#define BEEP_GPIO_GROUP 0 //蜂鸣器用的是GPIO0.7
#define BEEP_PIN 1 << 7
#define beep_on()
gpio_clr(BEEP_GPIO_GROUP, BEEP_PIN)
#define beep_off() gpio_set(BEEP_GPIO_GROUP, BEEP_PIN)
#define BEEP_TSK_NAME "Beep"
xTaskHandle g_beep_handle = (void*)0;
extern xSemaphoreHandle g_sem_handle;
//通过按键任务的信号量使蜂鸣器任务进入就绪态
void beep_tsk(void* p_ms)
{
while(1)
{
xSemaphoreTake(g_sem_handle, portMAX_DELAY); //等待按键给出的信号量g_sem_handle的到来,如果有信号量出现,继续往下执行
beep_on();
//beep_off();
vTaskDelay(configTICK_RATE_HZ * BEEP_TSK_DLY_MS/ 1000);
beep_off();
}
}
t_rtn beep_init(void)
{
gpio_set_pin_as_io(BEEP_GPIO_GROUP, BEEP_PIN);
gpio_set_output(BEEP_GPIO_GROUP, BEEP_PIN);
beep_off();
if(xTaskCreate(beep_tsk, BEEP_TSK_NAME, BEEP_TSK_STK_SIZE, INVALID_PTR, BEEP_TSK_PRI, &g_beep_handle) == pdTRUE)
//errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY
{
return NO_ERR;
}
else
{
return TASK_CREATE_FAIL;
}
}
千万不要删除行尾的分节符,此行不会被打印。不要在此行和下页的注释之间填写任何内容
下面的内容是参考文献,通过“插入”“引用”“脚注和尾注”,插入尾注到“文档结尾”后,word会自动生成序号。双击序号能自动定位。移动引用位置会自动重新编号。还可以插入“交叉引用”,实现对一篇文献的多次引用。
因为本人能力所限,不能将其自动放入前面的“参考文献”章节内,也不能去掉接下来的这半条直线,所以就只能麻烦您这么做了:
打印前,备份文档,然后将下面的内容copy & paste到“参考文献”内,并要手工修改序号。
注意!copy前一定要备份!以后再做修改时,要修改备份文档。
1 / 12