關於藍牙模塊WLT8266的USART通信總結

2019-07-19 20:17发布

本帖最后由 夏天的123 于 2019-1-4 10:01 编辑

本人使用STM32F030  MCU與WLT8266藍牙模塊進行USART通訊調試,在調試過程中,
為方便查看數據發送與恢復,在MCU與藍牙的TX,RX處還有藍牙的GND處引出三條線,
通過USB轉TLL連接電腦上的串口軟件;

1.時鐘用網上標準,定時器3設置500ms一次中斷,可是實際測試中發現定時器是1.5S一次中斷,足足多了2倍;
公式計算:(1+TIM_Prescaler )*(1+TIM_Period )/48000000=500ms沒錯,忽然想到時鐘可能不對,
TIME3時鐘由PLL提供,而PLL是2倍頻,外部晶振8Mhz,要達到48Mhz,那就要6倍頻,剛好小了3倍,修改即可;
void Timer3Init(void){        
   TIM_TimeBaseInitTypeDef TIM_TimeBaseStructre;     
   TIM_DeInit(TIM3);      
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //enable timer 3   
   TIM_TimeBaseStructre.TIM_Prescaler = 999;//500ms//     
   //TIM_TimeBaseStructre.TIM_Prescaler = 1999;//1s//   
   TIM_TimeBaseStructre.TIM_CounterMode = TIM_CounterMode_Up;     
   TIM_TimeBaseStructre.TIM_Period = 23999;   
   TIM_TimeBaseStructre.TIM_ClockDivision = TIM_CKD_DIV1;   
     //this parameter is only valid for TIM1 TIM_TimeBaseStructre.TIM_RepetitionCounter     
   TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructre);   
    TIM_ClearFlag(TIM3, TIM_FLAG_Update);   
    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);   
    TIM_Cmd(TIM3, ENABLE);}RCC_DeInit();


RCC_HSEConfig(RCC_HSE_ON);
if (RCC_WaitForHSEStartUp() == SUCCESS)
{      RCC_PREDIV1Config(RCC_PREDIV1_Div1);
       RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_2);   
      RCC_PLLCmd(ENABLE);     
     while( RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET )   
    {        }      
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);     
   while( RCC_GetSYSCLKSource() != 0x08 );   
    {        }      
  RCC_HCLKConfig(RCC_SYSCLK_Div1);   
     RCC_PCLKConfig(RCC_HCLK_Div1);}


2.APP連接藍牙模塊后,MCU給藍牙模塊發送數據,串口軟件收到,APP未收到,但是APP發送數據,MCU收到了;
原因1:藍牙USART 3.3V驅動不夠?(檢查后3.3V正常,排除)
原因2:藍牙模塊損壞?(再試另一藍牙模塊,還是收不到,排除)
原因3:藍牙與APP沒有真正連接成功?(APP發送MCU可以接受說明藍牙連接沒問題,排除)
原因4:USB_TLL線對藍牙模塊有干擾?(去掉無影響,排除)
原因5:USART 接受邏輯有問題?(有可能,查看問題4)


3.AT指令在初始化時該如何使用?
WLT8266模塊上電后進入AT模式,與APP連接后進入透傳模式(切忌在AT模式下發送透傳指令,如果你的MCU在接收到
錯誤命令后還有回復的話,那後果是很可怕的);所以可以在連接APP之前對其進行
AT初始化修改,一般出廠都有默認值,你可以修改設備名,波特率,設置廣播時間和發射功率,
設置完後進行復位是修改值生效;(我只修改了設備名)
AT_DataSend("AT+STOPADVERTISING ");
AT_DataSend("AT+GETADDRESS ");
AT_DataSend("AT+SETNAME=BLE100 ");
AT_DataSend("AT+STARTADVERTISING ");

AT_DataSend("AT+RESET ");//軟件復位,使設備名生效//
一般只設置一次就好了,可以設置一個標誌值放在MCU FLASH中,在開始處讀取并判斷,避免每次上電都用AT命令設置;
實際在發送AT指令時,發現藍牙模塊回復的信息後面由多個 ,發現是初始化使能接收中斷後,TDR寄存器發出的空字節
TXE=1沒有及時處理,導致不停的進入中斷,接收判斷沒有包含RxData[RxCnt] =RxDataTemp;雖然進不了接收判斷但一直在給
RxData[RxCnt]賦最後一次接收到的值 ,抱進來即可;
if((USART_GetFlagStatus(USART2, USART_FLAG_RXNE)!=RESET))
        {
        RxDataTemp=USART_ReceiveData(USART2);//RESET
        USART_ClearFlag(USART2,USART_FLAG_RXNE);

       }
RxData[RxCnt] =RxDataTemp;
在TDR寄存器發送空字節后,USART_GetFlagStatus(USART2, USART_FLAG_TC)=SET;
此時無論是接收使能還是發送使能他都是可以進入IF判斷的,因為STM32F030 接收和發送中斷在一塊;
USART_ClearFlag(USART2,USART_FLAG_TC);        后變RESET,發送完數據后又變SET以方便下一次發送;
所以根據自己中斷需要做相應處理;
if(USART_GetFlagStatus(USART2, USART_FLAG_TC) != RESET)
        {
                USART_ClearFlag(USART2,USART_FLAG_TC);        //RESET
                USART_SendData(USART2, TxData[TxCnt++]);//SET        
                USART_ITConfig(USART2, USART_IT_TC, DISABLE);
                USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
        }



4.有時接受第一次數據正常,接收第二次數據就不能完全接收,試了很多次后發現是USART 接收中斷設置的問題,
沒有添加中斷過濾;在RXNE=1 的的条件下(也就是上次数据还没有读走),串口移位寄存器又接收好了一个字节的数据并准备往RDR 寄存器去转移的时候,会由硬件将这个位置1。由软件向USART_ICR 寄存器的ORECF 位写1,可以清除这个标志。
如果USART_CR1 寄存器中的RXNEIE 位或EIE 位是1,就会产生中断请求。所以要清除該中斷標誌;這也是APP連接藍牙模塊后,
APP發送數據,MCU因接受不正確沒有正常返回數據的原因;
       if((USART_GetFlagStatus(USART2,USART_FLAG_ORE)!=RESET))
        {
        USART_ReceiveData(USART2);
        USART_ClearFlag(USART2,USART_FLAG_ORE);
        }
         if((USART_GetFlagStatus(USART2, USART_FLAG_RXNE)!=RESET))
        {
        RxDataTemp=USART_ReceiveData(USART2);//RESET
        USART_ClearFlag(USART2,USART_FLAG_RXNE);

        RxData[RxCnt] =RxDataTemp;
        }
5.要清楚你的APP是適用IOS版(蘋果手機)還是安卓版,不然APP可能連接不上藍牙模塊;

6.處理好接收數據和發送數據,基本的清楚了,後面的錯誤往往是一些邏輯小問題,
凡事總須研究才能明白,敲代碼更是這樣了。



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
3条回答
夏天的123
2019-07-20 01:53
        如果沒有外部晶振,則可以使用內部時鐘 :

       RCC_DeInit();//将外设 RCC寄存器重设为缺省值  
        RCC_HSICmd(ENABLE);//使能HSI   
        while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);//等待HSI使能成功        
        //FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);  
        //FLASH_SetLatency(FLASH_Latency_2);  
         
        RCC_HCLKConfig(RCC_SYSCLK_Div1);      // AHP不分频  
        RCC_PCLKConfig(RCC_HCLK_Div1);        //APB clock = HCLK 不分频         
        //设置 PLL 时钟源及倍频系数
        RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_8);//使能或者失能 PLL,这个
        参数可以取:ENABLE或者DISABLE   
        RCC_PLLCmd(ENABLE);//如果PLL被用于系统时钟,那么它不能被失能  
        //等待指定的 RCC 标志位设置成功 等待PLL初始化成功  
        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);  
      
        //设置系统时钟(SYSCLK) 设置PLL为系统时钟源  
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//选择想要的系统时钟   
        //等待PLL成功用作于系统时钟的时钟源  
        //  0x00:HSI 作为系统时钟   
        //  0x04:HSE作为系统时钟   
        //  0x08:PLL作为系统时钟   
        while(RCC_GetSYSCLKSource() != 0x08);//需与被选择的系统时钟对应起来,RCC_SYS
        CLKSource_PLL  

一周热门 更多>