目錄
一 串口介紹
1.常用函數(shù)介紹
串口發(fā)送/接收函數(shù):
串口中斷回調(diào)函數(shù):
狀態(tài)標(biāo)記變量:
?2.串口接收中斷流程?編輯
3.串口實(shí)驗(yàn)(非中斷)
?編程實(shí)現(xiàn):
4.串口實(shí)驗(yàn)(中斷)
編程實(shí)現(xiàn):
二 藍(lán)牙
非中斷
中斷
連接藍(lán)牙模塊
?三 Wifi
1.Wifi模塊基本接收和使用
2.WiFi連接服務(wù)器
3.Wifi服務(wù)器
?四 4G
一 串口介紹
參考51系列文章:
(54條消息) C51:串口_我有在好好學(xué)習(xí)的博客-CSDN博客
(54條消息) C51:藍(lán)牙/Wifi/4G 無線控制開關(guān)_c51藍(lán)牙_我有在好好學(xué)習(xí)的博客-CSDN博客
1.常用函數(shù)介紹
串口發(fā)送/接收函數(shù):
HAL_UART_Transmit(); 串口發(fā)送數(shù)據(jù),使用超時管理機(jī)制
HAL_UART_Receive(); 串口接收數(shù)據(jù),使用超時管理機(jī)制
HAL_UART_Transmit_IT(); 串口中斷模式發(fā)送
HAL_UART_Receive_IT(); 串口中斷模式接收
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart,uint8_t *pData, uint16_t Size, uint32_t Timeout)
作用:以阻塞的方式發(fā)送指定字節(jié)的數(shù)據(jù)
形參 1 :UART_HandleTypeDef 結(jié)構(gòu)體類型指針變量
形參 2:指向要發(fā)送的數(shù)據(jù)地址
形參 3:要發(fā)送的數(shù)據(jù)大小,以字節(jié)為單位
形參 4:設(shè)置的超時時間,以ms單位
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart,uint8_t *pData, uint16_t Size)
作用:以中斷的方式接收指定字節(jié)的數(shù)據(jù)
形參 1 是 UART_HandleTypeDef 結(jié)構(gòu)體類型指針變量
形參 2 是指向接收數(shù)據(jù)緩沖區(qū)
形參 3 是要接收的數(shù)據(jù)大小,以字節(jié)為單位
此函數(shù)執(zhí)行完后將清除中斷,需要再次調(diào)用以重新開啟中斷。
串口中斷回調(diào)函數(shù):
HAL_UART_IRQHandler(UART_HandleTypeDef *huart); //串口中斷處理函數(shù)
HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart); //發(fā)送中斷回調(diào)函數(shù)
HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); //接收中斷回調(diào)函數(shù)
狀態(tài)標(biāo)記變量:
USART_RX_STA
從0開始,串口中斷接收到一個數(shù)據(jù)(一個字節(jié))就自增1。當(dāng)數(shù)據(jù)讀取全部OK時候(回車和換行符號來的時候),那么 USART_RX_STA的最高位置1,表示串口數(shù)據(jù)接收全部完畢了,然后main函數(shù)里面可以處理數(shù)據(jù)了。
?2.串口接收中斷流程
3.串口實(shí)驗(yàn)(非中斷)
需求:
接受串口工具發(fā)送的字符串,并將其發(fā)送回串口工具。
硬件接線:
TX -- A10
RX -- A9
一定要記得交叉接線??!
串口配置:
1. 選定串口
?2. 選擇模式
異步通訊
3. 串口配置
4. 使用MicroLIB庫
從魔術(shù)棒打開,這個勾勾一定要打上,否則 printf 無法重映射!
?編程實(shí)現(xiàn):
重寫了printf
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <string.h>
/* USER CODE END Includes */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int fputc(int ch, FILE *f)
{
unsigned char temp[1]={ch};
HAL_UART_Transmit(&huart1,temp,1,0xffff);
return ch;
}
/* USER CODE END 0 */
//=============================================================================
/* USER CODE BEGIN 1 */
uint8_t str[] = "hello world\r\n";
uint8_t ch[21];
memset(ch,'\0',21);
/* USER CODE END 1 */
/* USER CODE BEGIN 2 */
HAL_UART_Transmit(&huart1,str,strlen(str),100); //串口發(fā)送數(shù)據(jù),使用超時管理機(jī)制
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_UART_Receive(&huart1,ch,20,100);//串口接收數(shù)據(jù),使用超時管理機(jī)制
//HAL_UART_Transmit(&huart1,str1,strlen(str1),100); //串口發(fā)送數(shù)據(jù),使用超時管理機(jī)制
printf(ch);
memset(ch,'\0',21);
}
/* USER CODE END 3 */
4.串口實(shí)驗(yàn)(中斷)
需求:
通過中斷的方法接受串口工具發(fā)送的字符串,并將其發(fā)送回串口工具。
硬件接線:
同上
串口配置:
前4步同上
5. 打開中斷
編程實(shí)現(xiàn):
覆寫函數(shù)的模板:直接復(fù)制粘貼
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
//串口接收緩存(1字節(jié))
uint8_t buf=0;
//定義最大接收字節(jié)數(shù) 200,可根據(jù)需求調(diào)整
#define UART1_REC_LEN 200
// 接收緩沖, 串口接收到的數(shù)據(jù)放在這個數(shù)組里,最大UART1_REC_LEN個字節(jié)
uint8_t UART1_RX_Buffer[UART1_REC_LEN];
// 接收狀態(tài)
// bit15, 接收完成標(biāo)志
// bit14, 接收到0x0d
// bit13~0, 接收到的有效字節(jié)數(shù)目
uint16_t UART1_RX_STA=0;
/* USER CODE END PV */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
// 接收完成回調(diào)函數(shù),收到一個數(shù)據(jù)后,在這里處理
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
// 判斷中斷是由哪個串口觸發(fā)的
if(huart->Instance == USART1)
{
// 判斷接收是否完成(UART1_RX_STA bit15 位是否為1)
if((UART1_RX_STA & 0x8000) == 0)
{
// 如果已經(jīng)收到了 0x0d (回車),
if(UART1_RX_STA & 0x4000)
{
// 則接著判斷是否收到 0x0a (換行)
if(buf == 0x0a)
// 如果 0x0a 和 0x0d 都收到,則將 bit15 位置為1
UART1_RX_STA |= 0x8000;
else
// 否則認(rèn)為接收錯誤,重新開始
UART1_RX_STA = 0;
}
else // 如果沒有收到了 0x0d (回車)
{
//則先判斷收到的這個字符是否是 0x0d (回車)
if(buf == 0x0d)
{
// 是的話則將 bit14 位置為1
UART1_RX_STA |= 0x4000;
}
else
{
// 否則將接收到的數(shù)據(jù)保存在緩存數(shù)組里
UART1_RX_Buffer[UART1_RX_STA & 0X3FFF] = buf;
UART1_RX_STA++;
// 如果接收數(shù)據(jù)大于UART1_REC_LEN(200字節(jié)),則重新開始接收
if(UART1_RX_STA > UART1_REC_LEN - 1)
UART1_RX_STA = 0;
}
}
}
// 重新開啟中斷
HAL_UART_Receive_IT(&huart1, &buf, 1);
}
}
//=================================================
/* USER CODE BEGIN 2 */
// 開啟接收中斷
HAL_UART_Receive_IT(&huart1, &buf, 1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//判斷判斷串口是否接收完成
if(UART1_RX_STA & 0x8000)
{
printf("收到數(shù)據(jù):");
// 將收到的數(shù)據(jù)發(fā)送到串口
HAL_UART_Transmit(&huart1, UART1_RX_Buffer, UART1_RX_STA & 0x3fff, 0xffff);
// 等待發(fā)送完成
while(huart1.gState != HAL_UART_STATE_READY);
printf("\r\n");
// 重新開始下一次接收
UART1_RX_STA = 0;
}
printf("=====\r\n");
HAL_Delay(1000);
}
/* USER CODE END 3 */
二 藍(lán)牙
非中斷
點(diǎn)亮板載LED,判斷接收的數(shù)據(jù)是否為“open”"close",如果不是就提示輸入錯誤,先用串口調(diào)試,再上藍(lán)牙模塊。
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
#include <stdio.h>
/* USER CODE END Includes */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
//覆寫printf
int fputc(int ch, FILE *f)
{
unsigned char temp[1]={ch};
HAL_UART_Transmit(&huart1,temp,1,0xffff);
return ch;
}
/* USER CODE END 0 */
//=============================================================================
/* USER CODE BEGIN 2 */
HAL_UART_Transmit(&huart1,(uint8_t *)"uart_start\r\n",strlen("uart_start\r\n"),100); //串口發(fā)送數(shù)據(jù),使用超時管理機(jī)制
/* USER CODE END 2 */
/* USER CODE BEGIN 3 */
HAL_UART_Receive(&huart1, ch, 19, 100);
//HAL_UART_Transmit(&huart1, ch, strlen(ch), 100);
//printf((char *)ch);
printf("%s", ch);
if (!strcmp((const char *)ch, "open")) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_RESET)
printf("LED1已打開\r\n");
}else if(!strcmp((const char *)ch, "close")) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_SET)
printf("LED1已關(guān)閉\r\n");
} else {
if(ch[0] != '\0')
printf("指令發(fā)送錯誤:%s\r\n", ch);
}
memset(ch, 0, strlen((const char *)ch));
}
/* USER CODE END 3 */
中斷
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
//串口接收緩存(1字節(jié))
uint8_t buf=0;
//定義最大接收字節(jié)數(shù) 200,可根據(jù)需求調(diào)整
#define UART1_REC_LEN 200
// 接收緩沖, 串口接收到的數(shù)據(jù)放在這個數(shù)組里,最大UART1_REC_LEN個字節(jié)
uint8_t UART1_RX_Buffer[UART1_REC_LEN];
// 接收狀態(tài)
// bit15, 接收完成標(biāo)志
// bit14, 接收到0x0d
// bit13~0, 接收到的有效字節(jié)數(shù)目
uint16_t UART1_RX_STA=0;
/* USER CODE END PV */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
// 接收完成回調(diào)函數(shù),收到一個數(shù)據(jù)后,在這里處理
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
// 判斷中斷是由哪個串口觸發(fā)的
if(huart->Instance == USART1)
{
// 判斷接收是否完成(UART1_RX_STA bit15 位是否為1)
if((UART1_RX_STA & 0x8000) == 0)
{
// 如果已經(jīng)收到了 0x0d (回車),
if(UART1_RX_STA & 0x4000)
{
// 則接著判斷是否收到 0x0a (換行)
if(buf == 0x0a)
// 如果 0x0a 和 0x0d 都收到,則將 bit15 位置為1
UART1_RX_STA |= 0x8000;
else
// 否則認(rèn)為接收錯誤,重新開始
UART1_RX_STA = 0;
}
else // 如果沒有收到了 0x0d (回車)
{
//則先判斷收到的這個字符是否是 0x0d (回車)
if(buf == 0x0d)
{
// 是的話則將 bit14 位置為1
UART1_RX_STA |= 0x4000;
}
else
{
// 否則將接收到的數(shù)據(jù)保存在緩存數(shù)組里
UART1_RX_Buffer[UART1_RX_STA & 0X3FFF] = buf;
UART1_RX_STA++;
// 如果接收數(shù)據(jù)大于UART1_REC_LEN(200字節(jié)),則重新開始接收
if(UART1_RX_STA > UART1_REC_LEN - 1)
UART1_RX_STA = 0;
}
}
}
// 重新開啟中斷
HAL_UART_Receive_IT(&huart1, &buf, 1);
}
}
//覆寫printf
int fputc(int ch, FILE *f)
{
unsigned char temp[1]={ch};
HAL_UART_Transmit(&huart1,temp,1,0xffff);
return ch;
}
/* USER CODE END 0 */
//=====================================================================================
/* USER CODE BEGIN 2 */
// 開啟接收中斷
HAL_UART_Receive_IT(&huart1, &buf, 1);
//啟動提示
HAL_UART_Transmit(&huart1,(uint8_t *)"uart_start\r\n",strlen("uart_start\r\n"),100);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//判斷判斷串口是否接收完成
if(UART1_RX_STA & 0x8000)
{
printf("收到數(shù)據(jù):");
if (!strcmp((const char *)UART1_RX_Buffer, "open")) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_RESET)
printf("LED1已打開\r\n");
}else if(!strcmp((const char *)UART1_RX_Buffer, "close")) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_SET)
printf("LED1已關(guān)閉\r\n");
} else {
if(UART1_RX_Buffer[0] != '\0')
printf("指令發(fā)送錯誤:%s\r\n", UART1_RX_Buffer);
}
memset(UART1_RX_Buffer, 0, strlen((const char *)UART1_RX_Buffer));
// 重新開始下一次接收
UART1_RX_STA = 0;
}
HAL_Delay(200);
}
/* USER CODE END 3 */
}
連接藍(lán)牙模塊
模塊波特率為9600
所以修改串口波特率
再連接模塊即可使用。?
?三 Wifi
1.Wifi模塊基本接收和使用
參考之前的文章
(55條消息) C51:藍(lán)牙/Wifi/4G 無線控制開關(guān)_c51藍(lán)牙_我有在好好學(xué)習(xí)的博客-CSDN博客文章來源地址http://www.zghlxwxcb.cn/news/detail-764316.html
2.WiFi連接服務(wù)器
?在接收中斷處理中加入一個是否接收到OK的判斷,改變標(biāo)志位AT_OK_FLAG,用這個標(biāo)志位卡住聯(lián)網(wǎng)過程,收到OK再繼續(xù)發(fā)下一個AT指令。
聯(lián)網(wǎng)完成后,服務(wù)器端會收到你設(shè)置的心跳包。并且開始進(jìn)行燈控指令的接收判斷。
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
#include <stdio.h>
/* USER CODE END Includes */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
//AT指令
char connecct_wifi[] = "AT+CWJAP=\"iQOO 5\",\"88888888\"\r\n";
char connect_server[] = "AT+CIPSTART=\"TCP\",\"192.168.138.144\",8880\r\n";
char CIPMODE[] = "AT+CIPMODE=1\r\n";
char CIPSEND[] = "AT+CIPSEND\r\n";
//是否收到OK標(biāo)志位,是否收到error標(biāo)志位,聯(lián)網(wǎng)狀態(tài)標(biāo)志位
uint8_t AT_OK_FLAG = 0;
uint8_t ERROR_FLAG = 0;
uint8_t NET_OK_FLAG = 0;
/* USER CODE END PD */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
//串口接收緩存(1字節(jié))
uint8_t buf=0;
//定義最大接收字節(jié)數(shù) 200,可根據(jù)需求調(diào)整
#define UART1_REC_LEN 200
// 接收緩沖, 串口接收到的數(shù)據(jù)放在這個數(shù)組里,最大UART1_REC_LEN個字節(jié)
uint8_t UART1_RX_Buffer[UART1_REC_LEN];
// 接收狀態(tài)
// bit15, 接收完成標(biāo)志
// bit14, 接收到0x0d
// bit13~0, 接收到的有效字節(jié)數(shù)目
uint16_t UART1_RX_STA=0;
/* USER CODE END PV */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
// 接收完成回調(diào)函數(shù),收到一個數(shù)據(jù)后,在這里處理
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
// 判斷中斷是由哪個串口觸發(fā)的
if(huart->Instance == USART1)
{
// 判斷接收是否完成(UART1_RX_STA bit15 位是否為1)
if((UART1_RX_STA & 0x8000) == 0)
{
// 如果已經(jīng)收到了 0x0d (回車),
if(UART1_RX_STA & 0x4000)
{
// 則接著判斷是否收到 0x0a (換行)
if(buf == 0x0a)
{
// 如果 0x0a 和 0x0d 都收到,則將 bit15 位置為1
UART1_RX_STA |= 0x8000;
//=================================
//判斷是否是已經(jīng)連上服務(wù)器,
//如果沒有,判斷有沒有收到AT指令返回的OK,ERROR
if(!NET_OK_FLAG)
{
if(!strcmp((const char *)UART1_RX_Buffer, "OK"))
AT_OK_FLAG = 1;
if(!strcmp((const char *)UART1_RX_Buffer, "ERROR"))
{
ERROR_FLAG = 1;
//收到ERROR,閃燈
for(i = 0;i<10;i++)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_9);
HAL_Delay(200);
}
}
}
//=================================
//如果已經(jīng)連上服務(wù)器,進(jìn)行燈控指令部分判斷
else
{
if (!strcmp((const char *)UART1_RX_Buffer, "open")) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_RESET)
printf("LED1已打開\r\n");
}else if(!strcmp((const char *)UART1_RX_Buffer, "close")) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_SET)
printf("LED1已關(guān)閉\r\n");
} else {
if(UART1_RX_Buffer[0] != '\0')
printf("指令發(fā)送錯誤:%s\r\n", UART1_RX_Buffer);
}
}
//=================================
//判斷結(jié)束,清空接收信息
memset(UART1_RX_Buffer, 0, UART1_REC_LEN);
// 重新開始下一次接收
UART1_RX_STA = 0;
}
else
// 否則認(rèn)為接收錯誤,重新開始
UART1_RX_STA = 0;
}
else // 如果沒有收到了 0x0d (回車)
{
//則先判斷收到的這個字符是否是 0x0d (回車)
if(buf == 0x0d)
{
// 是的話則將 bit14 位置為1
UART1_RX_STA |= 0x4000;
}
else
{
// 否則將接收到的數(shù)據(jù)保存在緩存數(shù)組里
UART1_RX_Buffer[UART1_RX_STA & 0X3FFF] = buf;
UART1_RX_STA++;
// 如果接收數(shù)據(jù)大于UART1_REC_LEN(200字節(jié)),則重新開始接收
if(UART1_RX_STA > UART1_REC_LEN - 1)
UART1_RX_STA = 0;
}
}
}
// 重新開啟中斷
HAL_UART_Receive_IT(&huart1, &buf, 1);
}
}
//覆寫printf
int fputc(int ch, FILE *f)
{
unsigned char temp[1]={ch};
HAL_UART_Transmit(&huart2,temp,1,0xffff);//發(fā)送給串口2
return ch;
}
//===================================main===========================================
/* USER CODE END 0 */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
// 開啟接收中斷
HAL_UART_Receive_IT(&huart1, &buf, 1);
//啟動提示
printf("uart_start\r\n");
//============聯(lián)網(wǎng)部分代碼=============
//給上電時間
HAL_Delay(2000);
//如果下面收到ERROR,從這里重新開始
retry:
//先清0
ERROR_FLAG = 0;
//開始聯(lián)網(wǎng)提示
printf("begin connection\r\n");
//發(fā)送第1個AT指令===========================
HAL_UART_Transmit(&huart1,(uint8_t *)connecct_wifi,strlen(connecct_wifi),100);
//如果收到OK,再繼續(xù)
while(!AT_OK_FLAG)
{
//判斷是否已經(jīng)ERR,如果ERR,重新開始聯(lián)網(wǎng)
if(ERROR_FLAG) goto retry;
HAL_Delay(50);
}
AT_OK_FLAG = 0;
printf("Wifi ON\r\n");
//發(fā)送第2個AT指令===========================
HAL_UART_Transmit(&huart1,(uint8_t *)connect_server,strlen(connect_server),100);
//如果收到OK,再繼續(xù)
while(!AT_OK_FLAG)
{
//判斷是否已經(jīng)ERR,如果ERR,重新開始聯(lián)網(wǎng)
if(ERROR_FLAG) goto retry;
HAL_Delay(50);
}
AT_OK_FLAG = 0;
printf("Server ON\r\n");
//發(fā)送第3個AT指令===========================
HAL_UART_Transmit(&huart1,(uint8_t *)CIPMODE,strlen(CIPMODE),100);
//如果收到OK,再繼續(xù)
while(!AT_OK_FLAG)
{
//判斷是否已經(jīng)ERR,如果ERR,重新開始聯(lián)網(wǎng)
if(ERROR_FLAG) goto retry;
HAL_Delay(50);
}
AT_OK_FLAG = 0;
printf("CIPMODE ON\r\n");
//發(fā)送第4個AT指令===========================
HAL_UART_Transmit(&huart1,(uint8_t *)CIPSEND,strlen(CIPSEND),100);
//如果收到OK,再繼續(xù)
while(!AT_OK_FLAG)
{
//判斷是否已經(jīng)ERR,如果ERR,重新開始聯(lián)網(wǎng)
if(ERROR_FLAG) goto retry;
HAL_Delay(50);
}
AT_OK_FLAG = 0;
printf("CIPSEND ON\r\n");
//聯(lián)網(wǎng)完成改變標(biāo)志位
NET_OK_FLAG = 1;
//聯(lián)網(wǎng)完成亮起指示燈
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET);
printf("NET OK\r\n");
/* USER CODE END 2 */
//===============================================================================
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//判斷判斷串口是否接收完成
//心跳包
HAL_UART_Transmit(&huart1,(uint8_t *)"stm32\r\n",strlen("stm32\r\n"),100);
HAL_Delay(1000);
}
/* USER CODE END 3 */
3.Wifi服務(wù)器
原理相同,基本上改變一些AT指令就可以了。
但是要注意,主機(jī)模式下收到的字符串形式如下
發(fā)送“ op ” ,實(shí)際上接收的結(jié)果為“ +IPD,0,2:op ”
直接用strcmp()沒法判斷,所以做了一個小字符串buffer,用來獲取 “ : ” 后的內(nèi)容
然后判斷buffer的內(nèi)容即可
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
#include <stdio.h>
/* USER CODE END Includes */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
//AT指令
//1 配置成雙模
uint8_t CWMODE[] = "AT+CWMODE=2\r\n";
//2 使能多鏈接
uint8_t CIPMUX[] = "AT+CIPMUX=1\r\n";
//3 建立TCPServer
uint8_t CIPSERVER[] = "AT+CIPSERVER=1\r\n";// default port = 333
//4 發(fā)送數(shù)據(jù)
uint8_t CIPSEND[] = "AT+CIPSEND=0,8\r\n";// 發(fā)送8個字節(jié)在連接0通道上
//是否收到OK標(biāo)志位,是否收到error標(biāo)志位,聯(lián)網(wǎng)狀態(tài)標(biāo)志位
uint8_t AT_OK_FLAG = 0;
uint8_t ERROR_FLAG = 0;
uint8_t NET_OK_FLAG = 0;
uint8_t i,j;//for用
uint8_t buffer[8];//接收開燈指令
uint8_t message_mark = 0;//判斷是否是來自客戶端的指令
/* USER CODE END PD */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
//串口接收緩存(1字節(jié))
uint8_t buf=0;
//定義最大接收字節(jié)數(shù) 200,可根據(jù)需求調(diào)整
#define UART1_REC_LEN 200
// 接收緩沖, 串口接收到的數(shù)據(jù)放在這個數(shù)組里,最大UART1_REC_LEN個字節(jié)
uint8_t UART1_RX_Buffer[UART1_REC_LEN];
// 接收狀態(tài)
// bit15, 接收完成標(biāo)志
// bit14, 接收到0x0d
// bit13~0, 接收到的有效字節(jié)數(shù)目
uint16_t UART1_RX_STA=0;
/* USER CODE END PV */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
// 接收完成回調(diào)函數(shù),收到一個數(shù)據(jù)后,在這里處理
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
// 判斷中斷是由哪個串口觸發(fā)的
if(huart->Instance == USART1)
{
// 判斷接收是否完成(UART1_RX_STA bit15 位是否為1)
if((UART1_RX_STA & 0x8000) == 0)
{
// 如果已經(jīng)收到了 0x0d (回車),
if(UART1_RX_STA & 0x4000)
{
// 則接著判斷是否收到 0x0a (換行)
if(buf == 0x0a)
{
// 如果 0x0a 和 0x0d 都收到,則將 bit15 位置為1
UART1_RX_STA |= 0x8000;
//=================================
//判斷是否是已經(jīng)連上服務(wù)器,
//如果沒有,判斷有沒有收到AT指令返回的OK,ERROR
if(!NET_OK_FLAG)
{
if(!strcmp((const char *)UART1_RX_Buffer, "OK"))
AT_OK_FLAG = 1;
if(!strcmp((const char *)UART1_RX_Buffer, "ERROR"))
{
ERROR_FLAG = 1;
//收到ERROR,閃燈
for(i = 0;i<10;i++)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_9);
HAL_Delay(200);
}
}
}
//=================================
//如果已經(jīng)連上服務(wù)器,進(jìn)行燈控指令部分判斷
else
{
//判斷是否是來自客戶端的信息,如果是就接收它
for(i = 0;i < UART1_REC_LEN;i++){
if(UART1_RX_Buffer[i] == ':' || message_mark){
if(UART1_RX_Buffer[i] == ':') i++;
message_mark = 1;
buffer[j] = UART1_RX_Buffer[i];
j++;
if(j >= 8) break;
}
}
message_mark = 0;
j = 0;
//根據(jù)來自客戶端的信息判斷開不開燈
if (!strcmp((const char *)buffer, "open")) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_RESET)
printf("LED1已打開\r\n");
memset(buffer, 0, 8);
}else if(!strcmp((const char *)buffer, "close")) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == GPIO_PIN_SET)
printf("LED1已關(guān)閉\r\n");
memset(buffer, 0, 8);
}
}
//=================================
//判斷結(jié)束,清空接收信息
memset(UART1_RX_Buffer, 0, UART1_REC_LEN);
// 重新開始下一次接收
UART1_RX_STA = 0;
}
else
// 否則認(rèn)為接收錯誤,重新開始
UART1_RX_STA = 0;
}
else // 如果沒有收到了 0x0d (回車)
{
//則先判斷收到的這個字符是否是 0x0d (回車)
if(buf == 0x0d)
{
// 是的話則將 bit14 位置為1
UART1_RX_STA |= 0x4000;
}
else
{
// 否則將接收到的數(shù)據(jù)保存在緩存數(shù)組里
UART1_RX_Buffer[UART1_RX_STA & 0X3FFF] = buf;
UART1_RX_STA++;
// 如果接收數(shù)據(jù)大于UART1_REC_LEN(200字節(jié)),則重新開始接收
if(UART1_RX_STA > UART1_REC_LEN - 1)
UART1_RX_STA = 0;
}
}
}
// 重新開啟中斷
HAL_UART_Receive_IT(&huart1, &buf, 1);
}
}
//覆寫printf
int fputc(int ch, FILE *f)
{
unsigned char temp[1]={ch};
HAL_UART_Transmit(&huart2,temp,1,0xffff);//發(fā)送給串口2
return ch;
}
/* USER CODE END 0 */
//==================================main====================================
/* USER CODE BEGIN 2 */
// 開啟接收中斷
HAL_UART_Receive_IT(&huart1, &buf, 1);
//啟動提示
printf("uart_start\r\n");
//=================================
//給上電時間
HAL_Delay(2000);
//如果下面收到ERROR,從這里重新開始
retry:
//先清0
ERROR_FLAG = 0;
//開始聯(lián)網(wǎng)提示
printf("begin connection\r\n");
//發(fā)送第1個AT指令===========================
HAL_UART_Transmit(&huart1,(uint8_t *)CWMODE,strlen((const char *)CWMODE),100);
//如果收到OK,再繼續(xù)
while(!AT_OK_FLAG)
{
//判斷是否已經(jīng)ERR,如果ERR,重新開始聯(lián)網(wǎng)
if(ERROR_FLAG) goto retry;
HAL_Delay(50);
}
AT_OK_FLAG = 0;
printf("Wifi ON\r\n");
//發(fā)送第2個AT指令===========================
HAL_UART_Transmit(&huart1,(uint8_t *)CIPMUX,strlen((const char *)CIPMUX),100);
//如果收到OK,再繼續(xù)
while(!AT_OK_FLAG)
{
//判斷是否已經(jīng)ERR,如果ERR,重新開始聯(lián)網(wǎng)
if(ERROR_FLAG) goto retry;
HAL_Delay(50);
}
AT_OK_FLAG = 0;
printf("Server ON\r\n");
//發(fā)送第3個AT指令===========================
HAL_UART_Transmit(&huart1,(uint8_t *)CIPSERVER,strlen((const char *)CIPSERVER),100);
//如果收到OK,再繼續(xù)
while(!AT_OK_FLAG)
{
//判斷是否已經(jīng)ERR,如果ERR,重新開始聯(lián)網(wǎng)
if(ERROR_FLAG) goto retry;
HAL_Delay(50);
}
AT_OK_FLAG = 0;
printf("CIPMODE ON\r\n");
//聯(lián)網(wǎng)完成改變標(biāo)志位
NET_OK_FLAG = 1;
//聯(lián)網(wǎng)完成亮起指示燈
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET);
printf("server OK\r\n");
/* USER CODE END 2 */
//==========================================
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//判斷判斷串口是否接收完成
//心跳包
HAL_UART_Transmit(&huart1,(uint8_t *)CIPSEND,strlen((const char *)CIPSEND),100);
HAL_Delay(2000);
HAL_UART_Transmit(&huart1,(uint8_t *)"stm32f1.",strlen("stm32f1."),100);
HAL_Delay(2000);
}
/* USER CODE END 3 */
?四 4G
和WIFI模塊一樣的操作,而且更加簡單,修改對應(yīng)的AT指令即可,主機(jī)搞個內(nèi)網(wǎng)穿透。
具體參考之前的文章,輕松愉快,不寫出來了。文章來源:http://www.zghlxwxcb.cn/news/detail-764316.html
(55條消息) C51:藍(lán)牙/Wifi/4G 無線控制開關(guān)_c51藍(lán)牙_我有在好好學(xué)習(xí)的博客-CSDN博客
到了這里,關(guān)于STM32:串口(藍(lán)牙/WIFI/4G)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!