先來看看程序運行的結果吧:
接下來就不說廢話了,自己看源代碼吧!每一行我都做了注釋:
首先是主函數(shù)main.c文件:
#include "stm32f10x.h" // Device header
#include "OLED.h"
#include "Serial.h"
#include "Delay.h"
#include "String.h"
#include "LED.h"
int main(void)
{
OLED_Init(); //oled 屏幕初始化
Serial_Init(); //串口初始化
LED_Init(); //LED燈初始化
while(1)
{
if(Rx_Flag) //如果接收到數(shù)據(jù)
{
if(strcmp(Rx_Data, "LED_ON") == 0) //如果接收到的數(shù)據(jù)是LED_ON
{
OLED_ShowString(1,1," "); //OLED顯示16個空格,清屏
LED_ON(); //執(zhí)行開燈函數(shù)
OLED_ShowString(1,1,Rx_Data); //OLED顯示LED_ON
Send_String("LED ON"); //串口發(fā)送LED ON,反饋控制者燈已經打開
}
else if(strcmp(Rx_Data, "LED_OFF") == 0) //如果接收到的數(shù)據(jù)是LED_OFF
{
OLED_ShowString(1,1," "); //OLED顯示16個空格,清屏
LED_OFF(); //執(zhí)行關燈函數(shù)
OLED_ShowString(1,1,Rx_Data); //OLED顯示LED_OFF
Send_String("LED OFF"); //串口發(fā)送LED OFF,反饋控制者燈已經關閉
}
Rx_Flag=0; //接收到數(shù)據(jù)標志位置0,為下次接收字符串做準備
}
Delay_ms(1000); //延時50毫秒,不用那么快
}
}
接下來是LED.h文件:
#ifndef __LED_H
#define __LED_H
void LED_Init(void);
void LED_ON(void);
void LED_OFF(void);
#endif
接下來是LED.c文件:
#include "stm32f10x.h" // Device header
// LED燈初始化函數(shù)
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct; //創(chuàng)建GPIOA初始化的結構體
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //推挽輸出模式
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5; //引腳5
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //頻率50MHz
GPIO_Init(GPIOA, &GPIO_InitStruct); //GPIOA初始化
GPIO_SetBits(GPIOA, GPIO_Pin_5); //引腳5設置高電平,防止LED燈初始化后亮
}
// 打開LED燈的函數(shù)
void LED_ON(void)
{
GPIO_ResetBits(GPIOA, GPIO_Pin_5); //引腳5置低電平
}
// 關閉LED燈的函數(shù)
void LED_OFF(void)
{
GPIO_SetBits(GPIOA, GPIO_Pin_5); //引腳5置高電平
}
記下來是串口相關的Serial.h文件:
#ifndef __SERIAL_H
#define __SERIAL_H
extern char Rx_Data[];
extern uint8_t Rx_Flag;
void Serial_Init(void);
void Send_Byte(uint8_t Byte);
void Send_String(char *str);
#endif
接下來就是最后一個serial.c文件了:
#include "stm32f10x.h" // Device header
char Rx_Data[100]; //創(chuàng)建接收字符串的變量能盛放100個字節(jié),閑小可以擴大
uint8_t Rx_Flag = 0; //創(chuàng)建接收到字符串的標志位。1表示接收到了字符串,0表示沒有接收到字符串
//串口初始化函數(shù)
void Serial_Init(void)
{
//1:RCC
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //開始串口1時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 開啟GPIOA的時鐘
//2:GPIO_init
GPIO_InitTypeDef GPIO_InitStruct; //創(chuàng)建GPIO初始化的結構體
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; // GPIO的模式為推挽輸出
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; //GPIO的引腳9
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //GPIO的頻率50MHz
GPIO_Init(GPIOA, &GPIO_InitStruct); //GPIO初始化
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; //GPIO的模式為上拉輸入
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; //GPIO引腳10
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //GPIO的頻率50MHz
GPIO_Init(GPIOA, &GPIO_InitStruct); //GPIO初始化
//3:USART_Init
USART_InitTypeDef USART_InitStruct; //創(chuàng)建串口初始化的結構體
USART_InitStruct.USART_BaudRate = 9600; // 波特率為9600
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 沒有硬件流控制
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 串口1的接收和發(fā)送模式
USART_InitStruct.USART_Parity = USART_Parity_No; // 串口無校驗
USART_InitStruct.USART_StopBits = USART_StopBits_1; // 串口停止位1位
USART_InitStruct.USART_WordLength = USART_WordLength_8b; // 串口數(shù)據(jù)位長度:8位
USART_Init(USART1, &USART_InitStruct); // 串口初始化
//4:NVIC_Init
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //NVIC的分組選擇2組
NVIC_InitTypeDef NVIC_InitStruct; //NVIC初始化的結構體
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn; //通道選擇串口1
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //NVIC串口通道使能
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; //NVIC搶占優(yōu)先級:1
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; //NVIC響應優(yōu)先級:1
NVIC_Init(&NVIC_InitStruct); //NVIC初始化
//5:USART_Cmd
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //開啟串口1的接收數(shù)據(jù)中斷
USART_Cmd(USART1, ENABLE); //串口1使能
}
// 發(fā)送字節(jié)的函數(shù)(參數(shù):8位的一個字節(jié))
void Send_Byte(uint8_t Byte)
{
USART_SendData(USART1, Byte); //發(fā)送1個字節(jié)
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); //等待發(fā)送完成的標志位置1,是0時就等待
USART_ClearFlag(USART1, USART_FLAG_TXE); //發(fā)送完成的標志位置0,為下次發(fā)送做準備
}
// 發(fā)送字符串函數(shù)(參數(shù)char類型的指針)
void Send_String(char *str)
{
while(*str) //如果解引用指針內容不是0就循環(huán)
{
Send_Byte(*str); //發(fā)送字節(jié)當前指針所指向的內容
str++; // 指針++,指向下一個字節(jié)的內容
}
}
// 串口1中斷函數(shù)
void USART1_IRQHandler(void)
{
static uint8_t state =0; // 定義接收狀態(tài)碼
static uint8_t i=0; //定義接收數(shù)組的下標
uint8_t Dat; //定義每次進中斷接收當前字節(jié)的變量
if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE)) //如果接收標志置位了
{
Dat = USART_ReceiveData(USART1); // 變量接收當前收到的字節(jié)
if(state == 0) // 如果狀態(tài)碼是0
{
if(Dat == '@') //如果收到的字節(jié)是@
{
state = 1; //狀態(tài)碼置1
}
}
else if(state == 1) // 如果狀態(tài)碼是1
{
if(Dat == '$') //如果收到的字節(jié)是$
{
state = 2; //狀態(tài)碼置2
}
else //否則
{
Rx_Data[i]=Dat; //接收數(shù)組的第i個下標賦值為當前接收的字節(jié)
i++; //下標++,移到數(shù)組下一個位置,準備下次接收
}
}
else if(state == 2) // 如果狀態(tài)碼是2
{
if(Dat == '&') //如果收到的字節(jié)是&
{
state = 0; //狀態(tài)碼置0 結束這次的接收
i = 0; //小標置0 這一串字符串接收完畢,下串從頭覆蓋
}
}
}
Rx_Flag = 1; // 接收標志位置1, 證明這段字符串接收完畢
USART_ClearFlag(USART1, USART_FLAG_RXNE); // 清除接收標志位
}
所有文件在工程中的目錄為:
文章來源:http://www.zghlxwxcb.cn/news/detail-853024.html
工程編譯后下載到單片機就能實現(xiàn)串口控制LED燈的亮滅了。文章來源地址http://www.zghlxwxcb.cn/news/detail-853024.html
到了這里,關于STM32通過串口發(fā)送指令控制LED燈亮滅OLED并顯示命令的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!