基于RT1064的电磁巡线小车
本文章是基于RT1064让智能小车实现电磁巡线。
提示:以下是本篇文章正文内容,下面案例可供参考
使用步骤
1.初始化参数
代码如下(示例):
DisableGlobalIRQ();
board_init();
//电机初始化
//右轮转动方向设置
gpio_init(D12, GPO, 0, GPIO_PIN_CONFIG);
gpio_init(D13, GPO, 0, GPIO_PIN_CONFIG);
//左轮转动方向设置
gpio_init(D14, GPO, 0, GPIO_PIN_CONFIG);
gpio_init(D15, GPO, 0, GPIO_PIN_CONFIG);
//初始化电机PWN
pwm_init(PWM1_MODULE3_CHB_D1, 1000, 10000);
pwm_init(PWM1_MODULE3_CHA_D0, 1000, 10000);
//舵机初始化
pwm_init(PWM4_MODULE2_CHA_C30, 50, 800);
//初始化ADC模块
adc_init(ADC_1,ADC1_CH4_B15,ADC_8BIT);
adc_init(ADC_1,ADC1_CH3_B14,ADC_8BIT);
//中断初始化
pit_init();
pit_interrupt_ms(PIT_CH1, 10);
EnableGlobalIRQ(0);
2.中断函数
代码如下(示例):
//AD采集
for(int i=0;i<10;i++)
{
adcnumber_right_value[i]=adc_convert(ADC_1,ADC1_CH4_B15);
adcnumber_left_value[i]=adc_convert(ADC_1,ADC1_CH3_B14);
}
adcnumber_right=(adcnumber_right_value[4]+adcnumber_right_value[5])/2;
adcnumber_left=(adcnumber_left_value[4]+adcnumber_left_value[5])/2;
//越界判断
if(adcnumber_right>10&&adcnumber_left>10)
{
gpio_set(D12, 0);
gpio_set(D13, 1);
gpio_set(D14, 0);
gpio_set(D15, 1);
}
else
{
gpio_set(D12, 0);
gpio_set(D13, 0);
gpio_set(D14, 0);
gpio_set(D15, 0);
}
//PID数据处理
PIDRegulation(&pid_value, adcnumber_left-adcnumber_right)
//舵机控制
pwn_serve=800+pid_value.result;
3.代码整体
main.c文件
#include "headfile.h"
uint32 pwn_serve_init = 800;
main(void)
{
DisableGlobalIRQ();
board_init();
//电机初始化
//右轮设置
gpio_init(D12, GPO, 0, GPIO_PIN_CONFIG);
gpio_init(D13, GPO, 0, GPIO_PIN_CONFIG);
//左轮设置
gpio_init(D14, GPO, 0, GPIO_PIN_CONFIG);
gpio_init(D15, GPO, 0, GPIO_PIN_CONFIG);
pwm_init(PWM1_MODULE3_CHB_D1, 1000, 10000);
pwm_init(PWM1_MODULE3_CHA_D0, 1000, 10000);
//舵机初始化
pwm_init(PWM4_MODULE2_CHA_C30, 50, 800);
//初始化ADC模块
adc_init(ADC_1,ADC1_CH4_B15,ADC_8BIT);
adc_init(ADC_1,ADC1_CH3_B14,ADC_8BIT);
//中断初始化
pit_init();
pit_interrupt_ms(PIT_CH1, 10);
EnableGlobalIRQ(0);
while (1)
{
//pwm_duty(PWM4_MODULE2_CHA_C30, pwn_serve_init);
}
}
isr.c文件
#include "headfile.h"
#include "isr.h"
typedef struct
typedef struct
{
int KP;//比例系数
int KI;//积分系数
int KD;//微分系数
int lasterror_1;//前一拍偏差
int lasterror_2;//前两拍偏差
int result;//输出值
}PID;
//初始化pid参数
PID pid_value={
3,0,30,0,0,0};
//ADC采集
int adcnumber_right_value[10]={
0};
int adcnumber_left_value[10]={
0};
int pwn_serve=800;
//PID算法
void PIDRegulation(PID *vPID, int thiserror)
{
vPID->result = vPID->KP * ( thiserror - vPID->lasterror_1 ) + vPID->KI * thiserror + vPID->KD * ( thiserror - 2 * vPID->lasterror_1 + vPID->lasterror_2 );
vPID->lasterror_2 = vPID->lasterror_1;
vPID->lasterror_1 = thiserror;
}
void CSI_IRQHandler(void)
{
CSI_DriverIRQHandler(); //调用SDK自带的中断函数 这个函数最后会调用我们设置的回调函数
__DSB(); //数据同步隔离
}
void PIT_IRQHandler(void)
{
if(PIT_FLAG_GET(PIT_CH0))
{
PIT_FLAG_CLEAR(PIT_CH0);
}
if(PIT_FLAG_GET(PIT_CH1))
{
int adcnumber_right=0;
int adcnumber_left=0;
//AD采集
for(int i=0;i<10;i++)
{
adcnumber_right_value[i]=adc_convert(ADC_1,ADC1_CH4_B15);
adcnumber_left_value[i]=adc_convert(ADC_1,ADC1_CH3_B14);
}
adcnumber_right=(adcnumber_right_value[4]+adcnumber_right_value[5])/2;
adcnumber_left=(adcnumber_left_value[4]+adcnumber_left_value[5])/2;
//越界判断
if(adcnumber_right>10&&adcnumber_left>10)
{
gpio_set(D12, 0);
gpio_set(D13, 1);
gpio_set(D14, 0);
gpio_set(D15, 1);
}
else
{
gpio_set(D12, 0);
gpio_set(D13, 0);
gpio_set(D14, 0);
gpio_set(D15, 0);
}
//PID数据处理
PIDRegulation(&pid_value, adcnumber_left-adcnumber_right);
//舵机控制
pwn_serve=800+pid_value.result;//800为舵机中值
pwm_duty(PWM4_MODULE2_CHA_C30,pwn_serve);
PIT_FLAG_CLEAR(PIT_CH1);//清除中断标记位
}
if(PIT_FLAG_GET(PIT_CH2))
{
PIT_FLAG_CLEAR(PIT_CH2);
}
if(PIT_FLAG_GET(PIT_CH3))
{
PIT_FLAG_CLEAR(PIT_CH3);
}
__DSB();
}
void GPIO2_Combined_16_31_IRQHandler(void)
{
if(GET_GPIO_FLAG(B15))
{
CLEAR_GPIO_FLAG(B15);//清除中断标志位
}
}
void GPIO2_Combined_0_15_IRQHandler(void)
{
if(GET_GPIO_FLAG(MT9V03X_VSYNC_PIN))
{
//不用清除标志位,标志位在mt9v03x_vsync函数内部会清除
if(1 == flexio_camera_type)mt9v03x_vsync();
}
if(GET_GPIO_FLAG(SCC8660_VSYNC_PIN))
{
//不用清除标志位,标志位在scc8660_vsync函数内部会清除
if(2 == flexio_camera_type)scc8660_vsync();
}
}
总结
注意事项(1)本文章的使用了tb6612电机驱动芯片对电机进行驱动。
(2)各个函数的操作都可以在相应的库里的.c文件和.h文件里查找。