前言:因为前段时间一直忙找工作的事情,完事了以后到时又催项目的进度,所以等了好久才进行第二篇的更新。这里主要说一些代码的实现,考虑到很多人大家用的单片机不太一样,所以我就没必要把整个工程都贴出来(作者的是KL26),有需要的可以留言发邮箱,所以这里就只贴出来主要部分代码。
1、整体结构
主要模块:一路PWM,一个PIT定时器(包括设置定时中断),一个串口(包括串口接受中断),若干GPIO。其对应的初始化为:
DisableInterrupts;
gpio_init (PTE2, GPO,0); // FENG MING
gpio_init (PTA17, GPI,1); // HONG WAI
uart_init (UART1, 9600); // 设置串口,9600波特率
tpm_pwm_init(TPM0, TPM_CH1,200,16); // 这个电调需要先给大概一毫秒的低电平,完成初始化,大约20%
TPM0_C1V=10000; // 先给PWM一个低占空比
pit_init_ms(PIT0,8); //定时bus时钟中断
set_vector_handler(PIT_VECTORn,pit0_hander); // 设置PIT中断服务函数到中断向量表里
set_vector_handler(UART1_VECTORn ,uart1_test_handler);
EnableInterrupts; // 使能所有中断
enable_irq(UART1_IRQn); // 使能串口中断
enable_irq(PIT_IRQn); // 使能PIT中断
uart_rx_irq_en(UART1); // 使能串口接收中断
2、串口模块:主要进行蓝牙串口数据的接受
除了串口初始化,设置接受中断外还需要在中断函数中进行串口数据的接受,以下是部分代码和注释:
void uart1_test_handler(void)
{
UARTn_e uratn = UART1;
if(UART_S1_REG(UARTN[uratn]) & UART_S1_RDRF_MASK) //接收数据寄存器满
{
uart_getchar(UART1,&Re_buff[counter]); //Re_buff是自己设置的一个数组,接受串口数据
if(counter==0&&Re_buff[0]!=0xA5) return; //Re_buff[0]!=0xA5 协议报头为0xA5
counter++;
if(counter==3) //Re_buff数组只接受三个字节,代表了手机发送的指令
{
counter=0;
sign=1;
}
}
3、PIT定时器:主要定时进行串口接收到的数据的解析
启动定时器中断是因为不能一直进行数据解析,因为串口数据需要不断的接受并更新。
Re_buff [ ]有三个字节,其中前两个字节也就是协议的报头为启动信号,0xA5和0x5A,设计这样两个报头的目的是为了防止滑板收到其他的蓝牙数据,导致滑板失控等现象的发生,一般0xA5和0x5A相邻出现的概率很小,如果你想更安全一些,可以多加几个字节作为协议的报头。第三个字节就是滑板的状态字节了,其中0x02 0x03 0x04 0x05 0xAA 0x0FF分别对应着手机上几个按键,eg: 当按下停车按钮时,手机会向滑板发送 0xA5 0x5A 0x0FF的信息,滑板通过辨别最后一个字节就会知道是停车。
接下来就是一个简单的处理,比如我通过第三个字节检测到要加速,我就可以通过设置A=0,A1=0,A2=0,B=0,C=1,D=0;(这几个变量是半夜三四点迷糊的时候瞎定的,后续也没改)这几个变量的值,也可以说是置标志位来进行接下来的处理,接下来的处理也就是控制PWM的占空比实现调速,代码实现在主函数的while循环中。
void pit0_hander()
{
if(PIT_TFLG(PIT0) == 1 ) //判断是否 PIT0 进入中断
{
if(sign)
{
sign=0;
if(Re_buff[0]==0xA5)
if(Re_buff[1]==0x5A) // 协议报头判断
{
if(Re_buff[2]==0x02) // 加速
{
A=0,A1=1,A2=0,B=0,C=0,D=0;
Re_buff[2]=0x00;
}
if(Re_buff[2]==0x03)
{
A=0,A1=0,A2=1,B=0,C=0,D=0;
Re_buff[2]=0x00;
}
if(Re_buff[2]==0x04)
{
A=0,A1=0,A2=0,B=1,C=0,D=0;
Re_buff[2]=0x00;
}
if(Re_buff[2]==0x05)
{
A=0,A1=0,A2=0,B=0,C=1,D=0;
Re_buff[2]=0x00;
}
if(Re_buff[2]==0xAA) // 启动
{
A=1,A1=0,A2=0,B=0,C=0,D=0;
Re_buff[2]=0x00;
}
if(Re_buff[2]==0xFF) // 停车
{
A=0,A1=0,A2=0,B=0,C=0,D=1;
Re_buff[2]=0x00;
}
}
}
duiguan=gpio_get(PTA17); // 以下部分如果不加光电对管可以忽略,主要实现自启停
if(!qidongflag)
if(!duiguan)
{
BmaCnt=25; // BmaCnt 为蜂鸣器设置,数值大小控制响的时间的长短
qidongflag=1;
}
if(pwm>=jishupwm)
if(qidongflag)
{
if(!duiguan)
{
zhanli++;
if(zhanli>600)
{
zhanli_flag=1;
zhanli=600;
}
}
if(zhanli_flag)
if(duiguan)
{
zhanli_flag=1;
zhanli--;
if(zhanli<400)
{
pwm=10000;
zhanli_flag=0;
}
}
}
if(BmaCnt > 0)
{
gpio_set (PTE2, 1);
BmaCnt--;
}
else
{
gpio_set (PTE2, 0);
}
PIT_Flag_Clear(PIT0); //清中断标志位
}
}
4、PWM控制:将PIT转换后的信息进行相应的PWM占空比的设置
举个例子就明白了:比如我加速的信号是0X02,这时候我在PIT中断里面判断第三个字节为0X02为预先设计的加速信号,所以设置了使 A=0,A1=1,A2=0,B=0,C=0,D=0;(在3部分代码中实现的),这里我要做的就是判断A1是否为1(只有这里置1了,其余的比如说减速停车信号时,该A1变量均为0),判断为1后进行PWM的设置,设置完之后,滑板就会自动进行加减速。部分实现代码如下:
while(1)
{
if(A&&!A1&&!A2&&!B&&!C&&!D)
qidongflag=1;
if(qidongflag)
{
if(!key_flag)
if(!A&&A1&&!A2&&!B&&!C&&!D) // 判断 只有A1置 1
{
key_flag=1;
A1=0; // 进来之后立马清除标志位
pwm=pwm+100; // PWM加100,进行加速
if(pwm>14000)
pwm=14000; // 控制最大速度,注意滑行安全
if(pwm<jishupwm)
pwm=jishupwm;
BmaCnt=15; // 每次手机发送指令,这边进行蜂鸣器哔哔提示,说明加速了
key_flag=0;
}
5、GPIO模块
进行蜂鸣器和光电对管的检测,其实就是一个高低电平的输出及检测判断,实现起来非常简单,这里就不贴代码了。
需要整个工程代码的可以留邮箱。。。