本帖最后由 夏天的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.處理好接收數據和發送數據,基本的清楚了,後面的錯誤往往是一些邏輯小問題,
凡事總須研究才能明白,敲代碼更是這樣了。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
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
一周热门 更多>