基于蓝牙SPP指令的手机控制LED
错误1:通信一直失败
能解决的办法:由于SPP通信指令格式为“APT+指令”,且结尾必须是”\r\n”,所以一直没有成功的建立和手机的通信。
错误2:可以接收到蓝牙的数据,但是接收不到手机发送的,只能接收到O和换行符
能解决的办法:把清除FIFOS那段代码删除,清除FIFOS会使得接收到的数据也被清除。同时也要把接收数据的函数写在main函数里而不是中断里。
硬件连接
硬件框图
UCF使用了串口和GPIO部分。同实验二。
软件编写
ASCII码表中: 0X30~0X39:阿拉伯数字0~9
0X41~0X5A:大写字母A~Z
0X61~0X7A小写字母a~z
由于蓝牙上电会发送“II”,连接到手机上回发送“IA”,发送数据成功会发送“OK”,接收到数据格式为APR+XXXX,故不适合用大写字母,而阿拉伯数字只有10个,LED有16个,也不适合用阿拉伯数字。
由于蓝牙接收到SPP密码“APT+SPP8888\r\n”之后,才能进行SPP通信,所以在程序初始化的时候,就发送SPP密码解锁蓝牙的SPP功能。AT指令还有很多,但是在这里用不到那些查询蓝牙连接状态,播放音乐,挂断来电,音量加减的指令。
16个灯就是:a b c d e f g h i j k l m n o p
手机发送字符过去,蓝牙接收到之后,发给FPGA。如果在0X60~0X71也就是a~p之间,减去0X60提取到灯的位数,然后0X0001左移位数写给LED就可以控制相应的LED。
软件流程图
实验结果和心得体会
用USB转TTL在电脑的串口助手上面调试的时候,数据收发完全没问题,但是一旦用手机来控制,就出现接收不到数据也发送不出来数据的问题。经过排查,首先是那个数据格式“APT+\r\n”,如果不是这个格式手机就收不到数据。第二个大坑是UART的clear fifos,刚开始写在中断里,就会导致收到的数据不完整。查了一个中午,终于,在把它写到主函数里之后,通信成功了!通过手机可以控制相应的LED亮。
代码:
#include "platform.h"
#include "xintc.h"
#include "xintc_i.h"
#include "xil_exception.h"//(硬件异常和软件异常处理)
#include "stdio.h"
#include "xuartlite.h"
#include "xuartlite_l.h"
#include "xparameters.h"
#include "xil_io.h"
#include "xgpio.h"
void print(char *str);
void Initialize(void);
void Uart_Handler(void);
XIntc IntCtrl;
XUartLite UART;
short flag_RX=0x00;
unsigned char RX_data=0x00;
u8 buf[32]="APT+SPP8888\r\n";
u8 buf_test[32]="APT+OK\r\n";
u8 buf1[32]="APT+";
u8 buf2[32]="\r\n";
u8 buf3[32]="LED NUM is";
XGpio LED;
int k=0 , j=0;
u16 LED_OUT=1;
int main()
{
print("programstart\r\n");
Initialize();
XGpio_DiscreteWrite(&LED,1,0xffff);
while(1)
{
////UART/////////////////////////////////////////////////////////////
//0X49:I 0XA:换行 0X4F:O 0X4B:K 0XD:回车
if(flag_RX)
{
flag_RX=0;
RX_data =Xil_In32(XPAR_UART_BASEADDR+0X00);//数据寄存器的偏移地址是0X00
xil_printf("UART received data 0x%X\r\n",RX_data);
XUartLite_Send(&UART,buf_test,13);
if(0x60<RX_data&&RX_data<0x71)//a~p
{
u8 temp=0;
temp=RX_data-0X61;
LED_OUT=0x0001<<temp;
XGpio_DiscreteWrite(&LED,1,LED_OUT);
}
if(RX_data==0x7A)//z
{
Xil_Out16(XPAR_LEDS_BASEADDR,0x0000);
}
if(RX_data==0x41)//A
{
for( k=0;k<2;k++){
for( j=0;j<15;j++){ XUartLite_SendByte(XPAR_UART_BASEADDR,buf[j]);} }
}
}//if (flag)
}
return 0;
}
void Initialize(void)
{
init_platform();
XIntc_Initialize(&IntCtrl , XPAR_INTC_DEVICE_ID);
////UART///////////////////////////////////////////////////////////// XUartLite_Initialize(&UART,XPAR_UART_DEVICE_ID);
XUartLite_ResetFifos(&UART);
while(XUartLite_IsTransmitFull(XPAR_UART_DEVICE_ID));
XUartLite_Send(&UART,buf,15);
XUartLite_EnableInterrupt(&UART);
XIntc_Connect(&IntCtrl,XPAR_INTC_0_UARTLITE_2_VEC_ID,(XInterruptHandler)Uart_Handler,(void*)&UART);
////LED////////////////////////////////////////////////////////////// XGpio_Initialize(&LED, XPAR_LEDS_DEVICE_ID);
XGpio_SetDataDirection(&LED,1,0x0000);//通道
XIntc_Enable(&IntCtrl,2);//UART
microblaze_enable_interrupts();
microblaze_register_handler((XInterruptHandler)XIntc_InterruptHandler,(void*)&IntCtrl);
XIntc_Start(&IntCtrl,XIN_REAL_MODE);
for( k=0;k<4;k++)
{
for( j=0;j<15;j++)
{
XUartLite_SendByte(XPAR_UART_BASEADDR,buf[j]);
}
}
}
void Uart_Handler(void)
{
int flag_UART;
//print("inthe intr\r\n");
flag_UART=Xil_In32(XPAR_UART_BASEADDR+0X08);//状态寄存器的偏移地址是0X08第8位是奇偶校验,错就返回1
if(flag_UART&0X01)
{
flag_RX = 1;
}
}