51单片机进行蓝牙通讯

问题遇到的现象和发生背景

学校的一个任务,用51单片机实现蓝牙通信。遇到的问题就是向蓝牙发送信息单片机没有响应,设计上要将从蓝牙获得的信息打印到OLED上。然而,从单片机端向蓝牙传递消息能引发串口中断并打印信息(但这个信息传递的方向不是我想要的啊。)
情况如下图所示

img


左边是单片机的串口,通过蓝牙发送信息1100,并成功在右侧蓝牙串口的接收端收到信息(注,蓝牙的功能测试完好)。
右边就是连接蓝牙的串口,通过蓝牙向单片机发送1111,在左侧也成功收到消息。
问题就是,在单片机的oled上应该显示发给单片机的1111,但是结果如下图。

img

即,从单片机向蓝牙接收端发送的信息引起了中断并达成了预期结果,可是方向不对啊……

问题相关代码,不完全,省去不相关的外设和代码块。//注释里有我提的一些问题,别管。

main函数主体

#include
#include
#include"oled.h"
#include"uart.h"
#include"bluetooth_show.h"

unsigned char cnt=0,x_stop=0,y_stop=0;

void Timer0Init(void)        //1毫秒@11.0592MHz
{
    TMOD &= 0xF0;        //设置定时器模式          即定时器中断
    TMOD |= 0x01;        //设置定时器模式
    TL0 = 0x66;        //设置定时初始值
    TH0 = 0xFC;        //设置定时初始值
    TF0 = 0;        //清除TF0标志
    ET0=1;            //打开中断开关
    TR0=1;  
}
//中断一用于按键
void timer0_ISR() interrupt 1
{
    TR0=0;
                                   //超时检测
    if(start_timer==1)
    {
        recv_timer0++;
        if(recv_timer0>MAV_WAUT)
        {    
            start_timer=0;
            recv_flag=1;
            recv_timer0=0;
            count=recv_cnt;        
            y_stop=Y_BEGIN+(count-1)/20;
            x_stop=X_BEGIN+(count-1)%20*6;
            recv_cnt=0;            
        }          
    }
    if(!keyA6&&!keyA7)//模式切换检测
    {
        cnt++;    //消抖
        if(cnt>10&&!keyA6&&!keyA7)
        {
            cnt=0;
            is_change=1;               //当同时按下A6A7时,is_change置反,在mian的循环中改变模式
            if(mode)mode=0;    //模式切换
            else mode=1;
            while(!keyA6&&!keyA7);          //松手等待
        }        
    }
    if(!keyA3&&mode==1)//左移闪烁
    {
        cnt++;    //消抖
        if(cnt>10&&!keyA3)
        {
            cnt=0;
            if(x!=X_BEGIN||y!=Y_BEGIN)
            {
                if(y!=Y_BEGIN&&x==X_BEGIN)
                {
                    x=X_END;
                    y--;
                    p2--;
                }
                else
                {
                    p2--;
                    x=x-6;
                }
                
            }
            while(!keyA3);          //松手等待
        }        
    }
    if(!keyA2&&mode==1)//右移闪烁
    {
        cnt++;    //消抖
        if(cnt>10&&!keyA2)
        {
            cnt=0;
            if(x!=x_stop||y!=y_stop)
            {                
                if(y!=y_stop&&x==X_END)
                {
                    x=X_BEGIN;
                    y++;
                    p2++;
                }
                else
                {
                    x=x+6;
                    p2++;
                }
                
            }
            while(!keyA2);          //松手等待
        }        
    }
}
//main函数主体
void main()
{    
    int s2=3;
    ring=0;
    //OLED初始化
    OLED_Init();

    //串口初始化         
    UartInit();
    Timer0Init();
    EA=1;             ////打开总中断开关    
    
    //以下为接收模式
    while(1)
    {
        if(is_change)    //修改菜单
        {
            unsigned char i=0;
            is_change=0;        //重置菜单改变标志位
            OLED_Set_Pos(0,0);
            for(;i<128;i++)      //清屏
            {                
                OLED_WR_Byte(0x00);        
            }
            switch(mode)
            {
                case 0:
                OLED_ShowString(0,0,"receive mode:",8);
                x=X_BEGIN;
                y=Y_BEGIN;
                break;
                case 1:
                OLED_ShowString(0,0,"send mode:",8);
                break;
            }
            mess_area();//消息框    
        }
        if(recv_flag==1&&mode==0)  //接收模式
        {
            clr_show_area();        //清除显示区
            beep();
            delay(1000);
            beep();
            ring=1;
            delay(10000);
            ring=0;
            delay(1000);
            beep();
            mess_show(count);    //接收消息并显示与OLED上
            //copy_buf();             //为什么这里要复制?为发送做准备?
            clr_buf(recv_buf);     //清除接收数组数据
            recv_flag=0;            
        }
        if(is_change==0&&mode==1)
        {
            mess_send(x,y);
            P1=(0xff<if(s2==9) s2=3;    //流水灯blingbling闪加持
            delay(10000);
             P1=0xff;
               
        }
    }         
}

//串口中断,这部分我不太了解,也许问题出在设置上?

/*
  蓝牙透传
  波特率9600
  数据位8
  停止位1
  无校验位

*/


#include"oled.h"
#include
#include"uart.h"

unsigned char value = 0;

unsigned char start_timer = 0;
unsigned char recv_buf[MAX_RECV];    //接受到的数据
unsigned char recv_cnt=0;
unsigned char recv_timer0=0;
unsigned char recv_flag=0;     //接受标志位,标志是否接收到信息
unsigned char mode =0; //模式标志,0为接收,1为发送
void UartInit(void)        //9600bps@11.0592MHz
{
    PCON &= 0x7F;        //波特率不倍速
    SCON = 0x50;        //8位数据,可变波特率   SCON 是一个特殊功能寄存器,用以设定串行口的工作方式、接收/发送控制以及设置状态标志
    TMOD &= 0x0F;        //设置定时器模式
    TMOD |= 0x20;        //设置定时器模式
    TL1 = 0xFD;        //设置定时初始值
    TH1 = 0xFD;        //设置定时重载值
    ET1 = 0;        //禁止定时器1中断
    TR1 = 1;        //定时器1开始计时
    ES=1;            //打开串口中断

}
void sendByte(unsigned char dat)
{
    /*
    SBUF=dat;                     //接收到的数据放入发送缓存器发送
    while(!TI);                     //等待发送数据完成
            */                        //清除发送完成标志位
    

    ES = 0;
    SBUF = dat;
    while (!TI);
    TI = 0;              //RI(SCON.0)或TI(SCON.1),串行口中断请求标志。
    ES = 1;

}
//中断检测

void uart_ISR() interrupt 4                      
{
    if(RI)                    //超时检测
    {
        RI=0;                 //中断标志位清零
        start_timer=1;
        if(recv_cnt0)
        {
            recv_buf[recv_cnt]=SBUF;         //从SBUF接收到的数据传递到承载数据的数组
            recv_cnt++;
            value=SBUF;                         //数组位数增加
        }                    
        recv_timer0=0;                          //为什么置零?
    }

    if(TI)
    {
        TI=0;                                 //外部中断标志位,详情看知识点,//发送中断标志,在方式1,2,3中由内部硬件置1,不清零就会一直发送。
    }
}


我的解答思路和尝试过的方法

1.用最简单的例程进行通信(主要是看看没有中断能不能通信),结果是能的,在两边都能收到信息
猜想:是不是连接串口的usb1和蓝牙都用到RXD和TXD,所以当蓝牙收到消息时直接能通过usb反应给串口,在串口助手上就能直接收到。看了看学校给的原理图,好像还真是。(下图右上角usb1原理图)不过我知道这个好像也没用,还是不懂为什么一个能引起中断一个不能……

img

2.之前看到一个说法,在烧录的时候不要插蓝牙会有影响,那反过来应该也一样?但是我试着不用烧录的usb口供电,蓝牙依旧无法引发串口中断,也没有任何现象。

我想要达到的结果

对蓝牙发送信息时,单片机能接收并反应在OLED上(OLED的事就不必了,只要说说怎么触发反应就好)
无解也是解,只要告诉我为啥无解就行。

你用的是蓝牙串口模块吧?
建议你首先将两个板子直接用串口连起来,而不经过蓝牙串口,看看能否正常显示,如果这样都不能,那通过蓝牙肯定也不行

另外,我看你这个代码容错性很差。通讯相关的程序,必须考虑通讯过程中的各种可能错误。解决办法,既有协议上的,也有算法上的。协议上,通讯过程常有的一个功能就是检测有效信息,你这个代码完全没有做这个。上电的时候很可能有一些杂乱信号被当成串口信号送过去占据了,而你的代码没有对这些做任何处理。

问题解决了吗,你给单片机下载完程序,跟ISP软件就没关系了,就剩下蓝牙USB转串口,就是一个数据收发

https://ask.csdn.net/questions/7553543?spm=1005.2026.3001.5635&utm_medium=distribute.pc_relevant_ask_down.none-task-ask-2~default~OPENSEARCH~Rate-3-7553543-ask-7773002.pc_feed_download_top3ask&depth_1-utm_source=distribute.pc_relevant_ask_down.none-task-ask-2~default~OPENSEARCH~Rate-3-7553543-ask-7773002.pc_feed_download_top3ask

额,怎么感觉上面的回答都扯远了。数据都接收到了,不就是OLED显示的问题吗?我看你的代码应该是Mode模式没有切换的原因吧?!
if(!keyA6&&!keyA7)//模式切换检测 这两个按键是不是要同时按下,还是松开可以切换模式的?
{
cnt++; //消抖
if(cnt>10&&!keyA6&&!keyA7)
{
cnt=0;
is_change=1; //当同时按下A6A7时,is_change置反,在mian的循环中改变模式
if(mode)mode=0; //模式切换
else mode=1;
while(!keyA6&&!keyA7); //松手等待
}