STM32實驗之USART串口發送+接受數據(二進制/HEX/文本)

涉及三個實驗:

1.USART串口發送和接收數據

我們使用的是將串口封裝成為一個Serial.c模塊.其中包含了

void Serial_Init(void);//串口初始化
void ?Serial_SendByte(uint8_t ?Byte);//串口發送一個字節
void Serial_SendArray(uint8_t *Array,uint16_t Length);//串口發送數組數據
void Serial_SendString(char *String);//串口發送字符串
void Serial_SendNumber(uint32_t Number,uint8_t Length);//串口發送數字uint8_t Serial_GetRxFlag(void);//串口接收標志位
uint8_t Serial_GetRxData(void);//接受數據模塊

在這次實驗中,我們調用中斷函數申請中斷,中斷函數為USART1_IRQHandler(void)
? 同時也要判斷在中斷中數據接收標志位,在最后也要清除中斷數據接受標志位if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
?? ?{
?? ??? ?Serial_RxData=USART_ReceiveData(USART1);
?? ??? ?Serial_RxFlag=1;
?? ??? ?USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清除標志位
?? ?}

1.1Serial.c串口模塊

#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>uint8_t Serial_RxData;
uint8_t Serial_RxFlag;
void Serial_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//復用推挽輸出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//引腳9為TX發送端GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//上拉輸入GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//引腳10為RX輸入端口GPIO_Init(GPIOB, &GPIO_InitStructure);//USART配置9600波特率 8位字長 1位停止位 無校驗位 無硬件流控制 只有發送模式USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate=9600;//波特率USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//硬件流控制選擇無USART_InitStructure.USART_Mode= USART_Mode_Tx | USART_Mode_Rx;//模式為發送信息USART_InitStructure.USART_Parity=USART_Parity_No;//無校驗位USART_InitStructure.USART_StopBits=USART_StopBits_1 ;//停止位占一位USART_InitStructure.USART_WordLength=USART_WordLength_8b ;//發送字長為8bitUSART_Init(USART1,&USART_InitStructure);//開啟RXNE標志位到NVIC的輸出,一旦RXEN標志位置1,就開始向NVIC申請中斷,之后,我們就可以在中斷里接受數據USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel= USART1_IRQn;//指定中斷通道NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//指定搶占優先級NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//指定響應優先級NVIC_Init(&NVIC_InitStructure);USART_Cmd(USART1,ENABLE);
}
//串口發送一個字節
void  Serial_SendByte(uint8_t  Byte)
{USART_SendData(USART1,Byte);//將將數據寫入發送數據寄存器中while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//發送數據寄存器是否發送完成,發送完成跳出循環
}//串口發送一個數組
// *Array 要發送數組的首地址
//Length 要發送數組的長度
void Serial_SendArray(uint8_t *Array,uint16_t Length)
{uint16_t i;for(i=0;i<Length;i++)//遍歷數組{Serial_SendByte(Array[i]);}
}//串口發送字符串
void Serial_SendString(char *String)
{uint8_t i;for(i=0;String[i]!='\0';i++){Serial_SendByte(String[i]);}
}//函    數:次方函數(內部使用)//返 回 值:返回值等于X的Y次方
uint32_t Serial_Pow(uint32_t X,uint32_t Y)
{uint32_t Result =1;while(Y--){Result *=X;}return Result;
}
//串口發送數字
//Number 要發送的數字,范圍:0~4294967295
//Length 要發送數字的長度,范圍:0~10
void Serial_SendNumber(uint32_t Number,uint8_t Length)
{uint8_t i;for(i=0;i<Length;i++)//根據數字長度遍歷數字的每一位{Serial_SendByte(Number/Serial_Pow(10,Length-i-1)%10+'0');}
}
//fputc為printf的底層,printf在打印的時候不斷調用fputc函數
int fputc(int ch,FILE *f)
{Serial_SendByte(ch);//在這里我們把fputc函數重定向到串口,那printf自然輸出到串口return ch;
}//將printf打印的內容輸出到串口
//將可變參數發送出去
void Serial_Printf(char *format,...)//format參數用來接收格式化字符串,...用來接收后面的可變參數列表
{char String[100];va_list arg;//定義一個參數列表變量va_start(arg,format);//從format位置開始接收參數表,放在arg里vsprintf(String,format,arg);va_end(arg);//釋放參數列表Serial_SendString(String);
}
//實現讀后自動清除
uint8_t Serial_GetRxFlag(void)
{if(Serial_RxFlag==1)//接受數據標志位置1,接收到數據{Serial_RxFlag=0;return 1;}return 0;
}
//變量封裝返回接收到的數據
uint8_t Serial_GetRxData(void)
{return Serial_RxData;
}
void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET){Serial_RxData=USART_ReceiveData(USART1);Serial_RxFlag=1;USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清除標志位}
}	

?1.2Serial.h函數

#ifndef __SERIAL_H
#define __SERIAL_Hvoid Serial_Init(void);//串口初始化
void  Serial_SendByte(uint8_t  Byte);//串口發送一個字節
void Serial_SendArray(uint8_t *Array,uint16_t Length);//串口發送數組數據
void Serial_SendString(char *String);//串口發送字符串
void Serial_SendNumber(uint32_t Number,uint8_t Length);//串口發送數字
void Serial_Printf(char *format,...);
uint8_t Serial_GetRxFlag(void);//接受數據標志位
uint8_t Serial_GetRxData(void);#endif

1.3 main.c函數

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"uint8_t RxData;			//定義用于接收串口數據的變量int main(void)
{OLED_Init();		//OLED初始化OLED_ShowString(1, 1, "RxData:");Serial_Init();		//串口初始化while (1){if (Serial_GetRxFlag() == 1)			//檢查串口接收數據的標志位{RxData = Serial_GetRxData();		//獲取串口接收的數據Serial_SendByte(RxData);			//串口將收到的數據回傳回去,用于測試OLED_ShowHexNum(1, 8, RxData, 2);	//顯示串口接收的數據}}
}

2.USART串口發送和接受HEX數據

在接受HEX數據包時使用一個狀態機的理念。

2.1狀態機代碼

	    RxData=USART_ReceiveData(USART1);if(RxState==0)/*當前狀態為0,接收數據包包頭*/{if(RxData==0xFF)//如果數據確實是包頭{RxState = 1;			//置下一個狀態pRxPacket = 0;			//數據包的位置歸零}}else if(RxState==1)/*當前狀態為1,接收數據包數據*/{Serial_RxPacket[pRxPacket]=RxData;//將數據存入數據包數組的指定位置pRxPacket++;//數據包的位置自增if(pRxPacket>=4)//如果收夠4個數據{RxState=2;//置下一個狀態}}else if(RxState==2)/*當前狀態為2,接收數據包包尾*/{if(RxData==0xFE)//如果數據確實是包尾部{RxState=0;//狀態歸0Serial_RxFlag=1;//接收數據包標志位置1,成功接收一個數據包}}

?2.2Serial.c串口模塊

#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>
//這里的數據只存儲發送和接受的載荷數據,包頭包尾不包含
uint8_t Serial_TxPacket[4];//發送的數據包
uint8_t Serial_RxPacket[4];//接收的數據包
uint8_t Serial_RxFlag;//收到數據標志位
uint8_t RxData;
void Serial_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//復用推挽輸出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//引腳9為TX發送端GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//上拉輸入GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//引腳10為RX輸入端口GPIO_Init(GPIOB, &GPIO_InitStructure);//USART配置9600波特率 8位字長 1位停止位 無校驗位 無硬件流控制 只有發送模式USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate=9600;//波特率USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//硬件流控制選擇無USART_InitStructure.USART_Mode= USART_Mode_Tx | USART_Mode_Rx;//模式為發送信息USART_InitStructure.USART_Parity=USART_Parity_No;//無校驗位USART_InitStructure.USART_StopBits=USART_StopBits_1 ;//停止位占一位USART_InitStructure.USART_WordLength=USART_WordLength_8b ;//發送字長為8bitUSART_Init(USART1,&USART_InitStructure);//開啟RXNE標志位到NVIC的輸出,一旦RXEN標志位置1,就開始向NVIC申請中斷,之后,我們就可以在中斷里接受數據USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel= USART1_IRQn;//指定中斷通道NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//指定搶占優先級NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//指定響應優先級NVIC_Init(&NVIC_InitStructure);USART_Cmd(USART1,ENABLE);
}void  Serial_SendByte(uint8_t  Byte)
{USART_SendData(USART1,Byte);//將將數據寫入發送數據寄存器中while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//發送數據寄存器是否發送完成,發送完成跳出循環
}void Serial_SendArray(uint8_t *Array,uint16_t Length)
{uint16_t i;for(i=0;i<Length;i++){Serial_SendByte(Array[i]);}
}void Serial_SendString(char *String)
{uint8_t i;for(i=0;String[i]!='\0';i++){Serial_SendByte(String[i]);}
}uint32_t Serial_Pow(uint32_t X,uint32_t Y)
{uint32_t Result =1;while(Y--){Result *=X;}return Result;
}
void Serial_SendNumber(uint32_t Number,uint8_t Length)
{uint8_t i;for(i=0;i<Length;i++){Serial_SendByte(Number/Serial_Pow(10,Length-i-1)%10+'0');}
}
//fputc為printf的底層,printf在打印的時候不斷調用fputc函數
int fputc(int ch,FILE *f)
{Serial_SendByte(ch);//在這里我們把fputc函數重定向到串口,那printf自然輸出到串口return ch;
}//將printf打印的內容輸出到串口
//將可變參數發送出去
void Serial_Printf(char *format,...)//format參數用來接收格式化字符串,...用來接收后面的可變參數列表
{char String[100];va_list arg;//定義一個參數列表變量va_start(arg,format);//從format位置開始接收參數表,放在arg里vsprintf(String,format,arg);va_end(arg);//釋放參數列表Serial_SendString(String);
}
//模塊:發送HEX數據包
void Serial_SendPacket(void)
{Serial_SendByte(0xFF);Serial_SendArray(Serial_TxPacket,4);Serial_SendByte(0xFE);
}
//實現讀后自動清除
uint8_t Serial_GetRxFlag(void)
{if(Serial_RxFlag==1)//接受數據標志位置1,接收到數據{Serial_RxFlag=0;return 1;}return 0;
}void USART1_IRQHandler(void)
{static uint8_t RxState=0;//定義表示當前狀態機狀態的靜態變量static uint8_t pRxPacket=0;//定義表示當前接收數據位置的靜態變量if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET){//使用狀態機機制//接收數據包的狀態機RxData=USART_ReceiveData(USART1);if(RxState==0)/*當前狀態為0,接收數據包包頭*/{if(RxData==0xFF)//如果數據確實是包頭{RxState = 1;			//置下一個狀態pRxPacket = 0;			//數據包的位置歸零}}else if(RxState==1)/*當前狀態為1,接收數據包數據*/{Serial_RxPacket[pRxPacket]=RxData;//將數據存入數據包數組的指定位置pRxPacket++;//數據包的位置自增if(pRxPacket>=4)//如果收夠4個數據{RxState=2;//置下一個狀態}}else if(RxState==2)/*當前狀態為2,接收數據包包尾*/{if(RxData==0xFE)//如果數據確實是包尾部{RxState=0;//狀態歸0Serial_RxFlag=1;//接收數據包標志位置1,成功接收一個數據包}}USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清除標志位}
}	

2.3Serial.h函數

#ifndef __SERIAL_H
#define __SERIAL_H#include <stdio.h>
extern uint8_t Serial_TxPacket[4];//外部可調用數組
extern uint8_t Serial_RxPacket[4];
void Serial_Init(void);
void  Serial_SendByte(uint8_t  Byte);
void Serial_SendArray(uint8_t *Array,uint16_t Length);
void Serial_SendString(char *String);
void Serial_SendNumber(uint32_t Number,uint8_t Length);
void Serial_Printf(char *format,...);uint8_t Serial_GetRxFlag(void);//這個函數判斷是不是接收到了數據包void Serial_SendPacket(void);void USART1_IRQHandler(void);#endif

2.4?main.c函數

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"
#include "Key.h"uint8_t KeyNum;			//定義用于接收按鍵鍵碼的變量int main(void)
{OLED_Init();		//OLED初始化Key_Init();			//按鍵初始化Serial_Init();		//串口初始化OLED_ShowString(1, 1, "TxPacket");OLED_ShowString(3, 1, "RxPacket");/*設置發送數據包數組的初始值,用于測試*/Serial_TxPacket[0] = 0x01;Serial_TxPacket[1] = 0x02;Serial_TxPacket[2] = 0x03;Serial_TxPacket[3] = 0x04;while (1){KeyNum = Key_GetNum();			//獲取按鍵鍵碼if (KeyNum == 1)				//按鍵1按下{Serial_TxPacket[0] ++;		//測試數據自增Serial_TxPacket[1] ++;Serial_TxPacket[2] ++;Serial_TxPacket[3] ++;Serial_SendPacket();		//串口發送數據包Serial_TxPacketOLED_ShowHexNum(2, 1, Serial_TxPacket[0], 2);	//顯示發送的數據包OLED_ShowHexNum(2, 4, Serial_TxPacket[1], 2);OLED_ShowHexNum(2, 7, Serial_TxPacket[2], 2);OLED_ShowHexNum(2, 10, Serial_TxPacket[3], 2);}if (Serial_GetRxFlag() == 1)	//如果接收到數據包{OLED_ShowHexNum(4, 1, Serial_RxPacket[0], 2);	//顯示接收的數據包OLED_ShowHexNum(4, 4, Serial_RxPacket[1], 2);OLED_ShowHexNum(4, 7, Serial_RxPacket[2], 2);OLED_ShowHexNum(4, 10, Serial_RxPacket[3], 2);}}
}

3.USART串口發送和接受文本數據

在接受文本數據包時使用一個狀態機的理念

3.1狀態機代碼

if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)	//判斷是否是USART1的接收事件觸發的中斷{uint8_t RxData = USART_ReceiveData(USART1);			//讀取數據寄存器,存放在接收的數據變量/*使用狀態機的思路,依次處理數據包的不同部分*//*當前狀態為0,接收數據包包頭*/if (RxState == 0){if (RxData == '@' && Serial_RxFlag == 0)		//如果數據確實是包頭,并且上一個數據包已處理完畢{RxState = 1;			//置下一個狀態pRxPacket = 0;			//數據包的位置歸零}}/*當前狀態為1,接收數據包數據,同時判斷是否接收到了第一個包尾*/else if (RxState == 1){if (RxData == '\r')			//如果收到第一個包尾{RxState = 2;			//置下一個狀態}else						//接收到了正常的數據{Serial_RxPacket[pRxPacket] = RxData;		//將數據存入數據包數組的指定位置pRxPacket ++;			//數據包的位置自增}}/*當前狀態為2,接收數據包第二個包尾*/else if (RxState == 2){if (RxData == '\n')			//如果收到第二個包尾{RxState = 0;			//狀態歸0Serial_RxPacket[pRxPacket] = '\0';			//將收到的字符數據包添加一個字符串結束標志Serial_RxFlag = 1;		//接收數據包標志位置1,成功接收一個數據包}}

?3.2Serial.c函數

#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>
//這里的數據只存儲發送和接受的載荷數據,包頭包尾不包含char Serial_RxPacket[100];//接收的數據包
uint8_t Serial_RxFlag;//收到數據標志位
uint8_t RxData;void Serial_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//復用推挽輸出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//引腳9為TX發送端GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//上拉輸入GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//引腳10為RX輸入端口GPIO_Init(GPIOB, &GPIO_InitStructure);//USART配置9600波特率 8位字長 1位停止位 無校驗位 無硬件流控制 只有發送模式USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate=9600;//波特率USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//硬件流控制選擇無USART_InitStructure.USART_Mode= USART_Mode_Tx | USART_Mode_Rx;//模式為發送信息USART_InitStructure.USART_Parity=USART_Parity_No;//無校驗位USART_InitStructure.USART_StopBits=USART_StopBits_1 ;//停止位占一位USART_InitStructure.USART_WordLength=USART_WordLength_8b ;//發送字長為8bitUSART_Init(USART1,&USART_InitStructure);//開啟RXNE標志位到NVIC的輸出,一旦RXEN標志位置1,就開始向NVIC申請中斷,之后,我們就可以在中斷里接受數據USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel= USART1_IRQn;//指定中斷通道NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//指定搶占優先級NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//指定響應優先級NVIC_Init(&NVIC_InitStructure);USART_Cmd(USART1,ENABLE);
}void Serial_SendByte(uint8_t Byte)
{USART_SendData(USART1, Byte);		//將字節數據寫入數據寄存器,寫入后USART自動生成時序波形while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);	//等待發送完成/*下次寫入數據寄存器會自動清除發送完成標志位,故此循環后,無需清除標志位*/
}void Serial_SendArray(uint8_t *Array,uint16_t Length)
{uint16_t i;for(i=0;i<Length;i++){Serial_SendByte(Array[i]);}
}void Serial_SendString(char *String)
{uint8_t i;for(i=0;String[i]!='\0';i++){Serial_SendByte(String[i]);}
}uint32_t Serial_Pow(uint32_t X,uint32_t Y)
{uint32_t Result =1;while(Y--){Result *=X;}return Result;
}
void Serial_SendNumber(uint32_t Number,uint8_t Length)
{uint8_t i;for(i=0;i<Length;i++){Serial_SendByte(Number/Serial_Pow(10,Length-i-1)%10+'0');}
}
//fputc為printf的底層,printf在打印的時候不斷調用fputc函數
int fputc(int ch,FILE *f)
{Serial_SendByte(ch);//在這里我們把fputc函數重定向到串口,那printf自然輸出到串口return ch;
}//將printf打印的內容輸出到串口
//將可變參數發送出去
void Serial_Printf(char *format,...)//format參數用來接收格式化字符串,...用來接收后面的可變參數列表
{char String[100];va_list arg;//定義一個參數列表變量va_start(arg,format);//從format位置開始接收參數表,放在arg里vsprintf(String,format,arg);va_end(arg);//釋放參數列表Serial_SendString(String);
}//實現讀后自動清除
uint8_t Serial_GetRxFlag(void)
{if(Serial_RxFlag==1)//接受數據標志位置1,接收到數據{Serial_RxFlag=0;return 1;}return 0;
}void USART1_IRQHandler(void)
{static uint8_t RxState=0;//靜態變量只能在本函數內使用static uint8_t pRxPacket=0;if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET){//接收數據包的狀態機RxData=USART_ReceiveData(USART1);if(RxState==0){if(RxData=='@' && Serial_RxFlag == 0){RxState=1;pRxPacket=0;}}else if(RxState==1){if(RxData=='\r'){RxState=2;}else{Serial_RxPacket[pRxPacket]=RxData;pRxPacket++;}}else if(RxState==2){if(RxData=='\n'){RxState=0;Serial_RxPacket[pRxPacket]='\0';Serial_RxFlag=1;}}USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清除標志位}
}	

3.3Serial.h函數

#ifndef __SERIAL_H
#define __SERIAL_H#include <stdio.h>extern char Serial_RxPacket[];
extern uint8_t Serial_RxFlag;void Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t *Array, uint16_t Length);
void Serial_SendString(char *String);
void Serial_SendNumber(uint32_t Number, uint8_t Length);
void Serial_Printf(char *format, ...);#endif

3.4main.c函數

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"
#include "LED.h"
#include "string.h"int main(void)
{/*模塊初始化*/OLED_Init();		//OLED初始化LED_Init();			//LED初始化Serial_Init();		//串口初始化/*顯示靜態字符串*/OLED_ShowString(1, 1, "TxPacket");OLED_ShowString(3, 1, "RxPacket");while (1){if (Serial_RxFlag == 1)		//如果接收到數據包{OLED_ShowString(4, 1, "                ");OLED_ShowString(4, 1, Serial_RxPacket);				//OLED清除指定位置,并顯示接收到的數據包/*將收到的數據包與預設的指令對比,以此決定將要執行的操作*/if (strcmp(Serial_RxPacket, "LED_ON") == 0)			//如果收到LED_ON指令{LED1_ON();										//點亮LEDSerial_SendString("LED_ON_OK\r\n");				//串口回傳一個字符串LED_ON_OKOLED_ShowString(2, 1, "                ");OLED_ShowString(2, 1, "LED_ON_OK");				//OLED清除指定位置,并顯示LED_ON_OK}else if (strcmp(Serial_RxPacket, "LED_OFF") == 0)	//如果收到LED_OFF指令{LED1_OFF();										//熄滅LEDSerial_SendString("LED_OFF_OK\r\n");			//串口回傳一個字符串LED_OFF_OKOLED_ShowString(2, 1, "                ");OLED_ShowString(2, 1, "LED_OFF_OK");			//OLED清除指定位置,并顯示LED_OFF_OK}else						//上述所有條件均不滿足,即收到了未知指令{Serial_SendString("ERROR_COMMAND\r\n");			//串口回傳一個字符串ERROR_COMMANDOLED_ShowString(2, 1, "                ");OLED_ShowString(2, 1, "ERROR_COMMAND");			//OLED清除指定位置,并顯示ERROR_COMMAND}Serial_RxFlag = 0;			//處理完成后,需要將接收數據包標志位清零,否則將無法接收后續數據包}}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/22872.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/22872.shtml
英文地址,請注明出處:http://en.pswp.cn/web/22872.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

fun()const->Iterator

先看一個函數定義如下&#xff1a; template <typename T> auto Blocker<T>::ObservedEnd() const -> Iterator {return observed_msg_queue_.end(); } 1 迭代器&#xff1a;Iterator 2 C auto 返回類型推導&#xff1a;-> Iterator 3 函數體限定不能修改…

【C語言】詳解函數(上)(庖丁解牛版)

文章目錄 1. 前言2. 函數的概念3.庫函數3.1 標準庫和頭文件3.2 庫函數的使用3.2.1 頭文件的包含3.2.2 實踐 4. 自定義函數4.1 自定義函數的語法形式4.2 函數的舉例 5. 形參和實參5.1 實參5.2 形參5.3 實參和形參的關系 6. return 語句6. 總結 1. 前言 一講到函數這塊&#xff…

棧排序00

題目鏈接 棧排序 題目描述 注意點 對棧進行排序使最小元素位于棧頂最多只能使用一個其他的臨時棧存放數據不得將元素復制到別的數據結構&#xff08;如數組&#xff09;中棧中的元素數目在[0, 5000]范圍內 解答思路 本題是要實現一個小頂堆&#xff0c;可以直接使用Priori…

上位機圖像處理和嵌入式模塊部署(f407 mcu中的udp server開發)

【 聲明&#xff1a;版權所有&#xff0c;歡迎轉載&#xff0c;請勿用于商業用途。 聯系信箱&#xff1a;feixiaoxing 163.com】 既然lwip已經port到407上面了&#xff0c;接下來其實就可以做一些測試了。本身lwip支持tcp、udp&#xff0c;也支持client和server&#xff0c;既然…

【數據分享】中國第三產業統計年鑒(1991-2022)

大家好&#xff01;今天我要向大家介紹一份重要的中國第三產業統計數據資源——《中國第三產業統計年鑒》。這份年鑒涵蓋了從1991年到2022年中國第三產業統計全面數據&#xff0c;并提供限時免費下載。&#xff08;無需分享朋友圈即可獲取&#xff09; 數據介紹 每年的《中國…

LeetCode.55 跳躍游戲

LeetCode.55 跳躍游戲 題目描述解題思路錯誤的解題思路解題思路 代碼 題目描述 解題思路 錯誤的解題思路 我一開始的思路是累加可跳范圍內的最大值sum&#xff0c;如果最終sum > nums.size()那么就返回true&#xff0c;這種思路是錯誤的&#xff0c;因為在你選擇最大值的…

2004NOIP普及組真題 3. FBI樹

線上OJ 地址&#xff1a; [04NOIP普及組] FBI樹 本題的意思是&#xff1a;給定一個 01字符串 &#xff08;對應一棵完全二叉樹的最后一層葉子節點&#xff09;&#xff0c;將樹的每一個節點的值用字母“F、B、I”表示。規則&#xff08;如下圖所示&#xff09;為&#xff1a; 1…

Spring AI 第二講 之 Chat Model API 第二節Ollama Chat

通過 Ollama&#xff0c;您可以在本地運行各種大型語言模型 (LLM)&#xff0c;并從中生成文本。Spring AI 通過 OllamaChatModel 支持 Ollama 文本生成。 先決條件 首先需要在本地計算機上運行 Ollama。請參閱官方 Ollama 項目 README&#xff0c;開始在本地計算機上運行模型…

curl 92 HTTP/2 stream 5 was not closed cleanly: CANCEL

source ~/.bash_profile flutter clean Command exited with code 128: git fetch --tags Standard error: 錯誤&#xff1a;RPC 失敗。curl 92 HTTP/2 stream 5 was not closed cleanly: CANCEL (err 8) 錯誤&#xff1a;預期仍然需要 2737 個字節的正文 fetch-pack: unexpec…

GPT革命:AI如何重塑我們的未來!

GPT革命&#xff1a;AI如何重塑我們的未來&#xff01; &#x1f604;生命不息&#xff0c;寫作不止 &#x1f525; 繼續踏上學習之路&#xff0c;學之分享筆記 &#x1f44a; 總有一天我也能像各位大佬一樣 &#x1f3c6; 博客首頁 怒放吧德德 To記錄領地 &#x1f31d;分享…

普通人也能弄的 16 個AI搞錢副業,門檻低,易上手!

大家好&#xff0c;我是靈魂畫師向陽 本期給大家分享的是利用AI 做副業的一些方法&#xff0c;大家可以挑選適合自己的賽道去搞錢 現在是人工智能時代&#xff0c;利用好AI 工具&#xff0c;可以降低普通人做副業的門檻&#xff0c;同時也能提高工作效率&#xff0c; 因此AI …

【微機原理與匯編語言】循環程序設計

一、實驗目的 1.熟練掌握8086/8088常用匯編指令的使用方法 2.熟練掌握循環結構程序編程技巧 3.熟練掌握匯編語言程序運行調試方法 二、實驗要求 認真分析實驗題目&#xff0c;設計程序流程圖&#xff0c;獨立完成代碼編寫及運行調試。 三、實驗題目 給出不大于255的十個…

圖片裁剪與上傳處理方案 —— 基于阿里云 OSS 處理用戶資料

目錄 01: 通用組件&#xff1a;input 構建方案分析 02: 通用組件&#xff1a;input 構建方案 03: 構建用戶資料基礎樣式 04: 用戶基本資料修改方案 05: 處理不保存時的同步問題 06: 頭像修改方案流程分析 07: 通用組件&#xff1a;Dialog 構建方案分析 08: 通用組件&…

計算機組成原理·考點知識點整理

根據往年考試題&#xff0c;對考點和知識點的一個整理。 校驗編碼 碼距 一種編碼的最小碼距&#xff0c;其實就是指這種編碼的碼距。碼距有兩種定義&#xff1a; 碼距所描述的對象含義 2 2 2 個特定的碼其二進制表示中不同位的個數一種編碼這種編碼中任意 2 2 2 個合法編碼的…

【linux進程控制(三)】進程程序替換--如何自己實現一個bash解釋器?

&#x1f493;博主CSDN主頁:杭電碼農-NEO&#x1f493; ? ?專欄分類:Linux從入門到精通? ? &#x1f69a;代碼倉庫:NEO的學習日記&#x1f69a; ? &#x1f339;關注我&#x1faf5;帶你學更多操作系統知識 ? &#x1f51d;&#x1f51d; 進程程序替換 1. 前言2. exec…

【JMeter接口自動化】第8講 Fiddler抓包Jmeter

1&#xff09;配置好Fiddler 設置Fiddler-Tools-Options-HTTPS 設置Fiddler-Tools-Options-Connections&#xff0c;設置端口為8888 2&#xff09;查看IP 在CMD中輸入ipconfig 查看IP地址 3&#xff09;配置Jmeter Http請求——基本&#xff0c;設置Http請求&#xff0c;使用…

輕量管理內核復雜級別的項目

在嵌入式開發中&#xff0c;管理大型項目&#xff08;例如Linux內核&#xff09;往往是一個復雜的過程。常規的版本控制系統如Git在處理小型項目時非常高效&#xff0c;但面對龐大的代碼庫時可能會顯得笨重且占用大量存儲空間。本文將介紹幾種輕量級的方法來管理內核級別的項目…

Python 快速入門

1. 語言基礎 1.1 數據類型與變量 Python 是一門動態類型語言&#xff0c;這意味著你不需要顯式聲明變量的類型。Python 解釋器會根據你賦予變量的值自動推斷其類型。這使得 Python 代碼簡潔易懂&#xff0c;但同時也需要注意一些潛在的問題。 1.1.1 Python 數據類型概述 Py…

408鏈表的創建和初始化

首先第一個頭文件&#xff0c;定義結構體類型 typedef struct LNode {int data;struct LNode* next; }LNode,*LinkList; //可能作為第一次寫c語言的小伙伴看不懂這一段typedef是如何定義的 //基本的解釋如下所示 //typedef struct LNode LNode; //typedef struct LNode* LinkL…

apex代碼發送郵件時進行抄送

在 Salesforce 中使用 Apex 代碼發送電子郵件時&#xff0c;可以通過 ccAddresses 屬性來添加抄送&#xff08;CC&#xff09;收件人。以下是一個示例代碼&#xff0c;展示了如何使用 Messaging.SingleEmailMessage 類來發送帶有抄送的電子郵件。 示例代碼 public class Emai…