(本文使用STM32F103C8T6,在CubeMX里演示用的是RBT6,但實際上引腳是一樣的)
????????本文著重解決一個大工程中,某些傳感器的例程是HAL庫的,而其他模塊(或算法)都是標(biāo)準(zhǔn)庫,導(dǎo)致難以移植的問題。本文的解決方法是:使用一片單片機用HAL庫(CubeMX)配置例程,然后用串口將傳感器數(shù)據(jù)傳給標(biāo)準(zhǔn)庫進(jìn)行處理。
????????首先,配置CubeMX,這是我一個項目的某個模塊配置的工程,其中,本文使用光學(xué)傳感器進(jìn)行演示(什么傳感器不重要),通信協(xié)議為IIC,串口使用UART2。
????????傳感器的接法:將SDA,SCL,VCC,GND依次接好即可,上圖有INT/SDA/SCL.......等引腳顯示,一個個接好就行了。
?時鐘:
????????最后GENERATE CODE,將這片HAL庫單片機的UART_TX接到標(biāo)準(zhǔn)庫單片機的UART_RX
配置標(biāo)準(zhǔn)庫單片機:
????????關(guān)鍵部分代碼:文章來源:http://www.zghlxwxcb.cn/news/detail-739942.html
usart.c
#include "sys.h"
#include "usart.h"
//如果使用ucos,則包括下面的頭文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h" //ucos 使用
#endif
#if 1
#pragma import(__use_no_semihosting)
//標(biāo)準(zhǔn)庫需要的支持函數(shù)
struct __FILE
{
int handle;
};
FILE __stdout;
//定義_sys_exit()以避免使用半主機模式
_sys_exit(int x)
{
x = x;
}
//重定義fputc函數(shù)
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//循環(huán)發(fā)送,直到發(fā)送完畢
USART1->DR = (u8) ch;
return ch;
}
#endif
#if EN_USART1_RX //如果使能了接收
//串口1中斷服務(wù)程序
//注意,讀取USARTx->SR能避免莫名其妙的錯誤
u8 USART1_RX_BUF[USART1_REC_LEN]; //接收緩沖,最大USART_REC_LEN個字節(jié).
//接收狀態(tài)
//bit15, 接收完成標(biāo)志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字節(jié)數(shù)目
u16 USART1_RX_STA=0; //接收狀態(tài)標(biāo)記
void uart1_init(u32 bound){
//GPIO端口設(shè)置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA時鐘
//USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//搶占優(yōu)先級3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子優(yōu)先級3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)指定的參數(shù)初始化VIC寄存器
//USART 初始化設(shè)置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長為8位數(shù)據(jù)格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//無奇偶校驗位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無硬件數(shù)據(jù)流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收發(fā)模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//開啟串口接受中斷
USART_Cmd(USART1, ENABLE); //使能串口1
}
void USART1_IRQHandler(void) //串口1中斷服務(wù)程序
{
u8 Res;
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS為真,則需要支持OS.
OSIntEnter();
#endif
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中斷(接收到的數(shù)據(jù)必須是0x0d 0x0a結(jié)尾)
{
Res =USART_ReceiveData(USART1); //讀取接收到的數(shù)據(jù)
if((USART1_RX_STA&0x8000)==0)//接收未完成
{
if(USART1_RX_STA&0x4000)//接收到了0x0d
{
if(Res!=0x0a)USART1_RX_STA=0;//接收錯誤,重新開始
else USART1_RX_STA|=0x8000; //接收完成了
}
else //還沒收到0X0D
{
if(Res==0x0d)USART1_RX_STA|=0x4000;
else
{
USART1_RX_BUF[USART1_RX_STA&0X3FFF]=Res ;
USART1_RX_STA++;
if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//接收數(shù)據(jù)錯誤,重新開始接收
}
}
}
}
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS為真,則需要支持OS.
OSIntExit();
#endif
}
#endif
#if EN_USART2_RX
u8 USART2_RX_BUF[USART2_REC_LEN]; //接收緩沖,最大USART_REC_LEN個字節(jié).末字節(jié)為換行符
u16 USART2_RX_STA = 0; //接收狀態(tài)標(biāo)記
void uart2_init(u32 bound)
{
GPIO_InitTypeDef GPIO_InitStrue;
USART_InitTypeDef USART_InitStrue;
NVIC_InitTypeDef NVIC_InitStrue;
// 外設(shè)使能時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
USART_DeInit(USART2); //復(fù)位串口2 -> 可以沒有
// 初始化 串口對應(yīng)IO口 TX-PA2 RX-PA3
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_2;
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStrue);
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_3;
GPIO_Init(GPIOA,&GPIO_InitStrue);
// 初始化 串口模式狀態(tài)
USART_InitStrue.USART_BaudRate=bound; // 波特率
USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None; // 硬件流控制
USART_InitStrue.USART_Mode=USART_Mode_Tx|USART_Mode_Rx; // 發(fā)送 接收 模式都使用
USART_InitStrue.USART_Parity=USART_Parity_No; // 沒有奇偶校驗
USART_InitStrue.USART_StopBits=USART_StopBits_1; // 一位停止位
USART_InitStrue.USART_WordLength=USART_WordLength_8b; // 每次發(fā)送數(shù)據(jù)寬度為8位
USART_Init(USART2,&USART_InitStrue);
USART_Cmd(USART2,ENABLE);//使能串口
USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);//開啟接收中斷
// 初始化 中斷優(yōu)先級
NVIC_InitStrue.NVIC_IRQChannel=USART2_IRQn;
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStrue);
}
void USART2_IRQHandler(void) // 串口2中斷服務(wù)函數(shù)
{
u8 res;
if(USART_GetITStatus(USART2,USART_IT_RXNE)) // 中斷標(biāo)志
{
res= USART_ReceiveData(USART2); // 串口2 接收
// USART_SendData(USART2,res); // 串口2 發(fā)送
if((USART2_RX_STA&0x8000)==0)//接收未完成
{
if(USART2_RX_STA&0x4000)//接收到了0x0d
{
if(res!=0x0a)USART2_RX_STA=0;//接收錯誤,重新開始
else USART2_RX_STA|=0x8000; //接收完成了
}
else //還沒收到0X0D
{
if(res==0x0d)USART2_RX_STA|=0x4000;
else
{
USART2_RX_BUF[USART2_RX_STA&0X3FFF]=res ;
USART2_RX_STA++;
if(USART2_RX_STA>(USART2_REC_LEN-1))USART2_RX_STA=0;//接收數(shù)據(jù)錯誤,重新開始接收
}
}
}
}
}
#endif
#if EN_USART3_RX
u8 USART3_RX_BUF[USART3_REC_LEN]; //接收緩沖,最大USART_REC_LEN個字節(jié).末字節(jié)為換行符
u16 USART3_RX_STA = 0; //接收狀態(tài)標(biāo)記
void uart3_init(u32 bound)
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // GPIOB時鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //串口3時鐘使能
USART_DeInit(USART3); //復(fù)位串口3
//USART3_TX PB10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB10
//USART3_RX PB11
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB11
USART_InitStructure.USART_BaudRate = bound;//波特率一般設(shè)置為9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長為8位數(shù)據(jù)格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//無奇偶校驗位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無硬件數(shù)據(jù)流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收發(fā)模式
USART_Init(USART3, &USART_InitStructure); //初始化串口 3
USART_Cmd(USART3, ENABLE); //使能串口
//使能接收中斷
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//開啟中斷
//設(shè)置中斷優(yōu)先級
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//搶占優(yōu)先級3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子優(yōu)先級3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)指定的參數(shù)初始化VIC寄存器
USART3_RX_STA=0; //清零
}
void USART3_IRQHandler(void) // 串口3中斷服務(wù)函數(shù)
{
u8 res;
if(USART_GetITStatus(USART3,USART_IT_RXNE)) // 中斷標(biāo)志
{
res= USART_ReceiveData(USART3); // 串口3 接收
// USART_SendData(USART2,res); // 串口3 發(fā)送
if((USART3_RX_STA&0x8000)==0)//接收未完成
{
if(USART3_RX_STA&0x4000)//接收到了0x0d
{
if(res!=0x0a)USART3_RX_STA=0;//接收錯誤,重新開始
else USART3_RX_STA|=0x8000; //接收完成了
}
else //還沒收到0X0D
{
if(res==0x0d)USART3_RX_STA|=0x4000;
else
{
USART3_RX_BUF[USART2_RX_STA&0X3FFF]=res ;
USART3_RX_STA++;
if(USART3_RX_STA>(USART3_REC_LEN-1))USART3_RX_STA=0;//接收數(shù)據(jù)錯誤,重新開始接收
}
}
}
}
}
#endif
usart.h
#ifndef __USART_H
#define __USART_H
#include "stdio.h"
#include "sys.h"
#define USART1_REC_LEN 200 //定義最大接收字節(jié)數(shù) 200
#define EN_USART1_RX 1 //使能(1)/禁止(0)串口1接收
extern u8 USART1_RX_BUF[USART1_REC_LEN]; //接收緩沖,最大USART_REC_LEN個字節(jié).末字節(jié)為換行符
extern u16 USART1_RX_STA; //接收狀態(tài)標(biāo)記
void uart1_init(u32 bound);
#define USART2_REC_LEN 200 //定義最大接收字節(jié)數(shù) 200
#define EN_USART2_RX 1 //使能(1)/禁止(0)串口2接收
extern u8 USART2_RX_BUF[USART2_REC_LEN]; //接收緩沖,最大USART_REC_LEN個字節(jié).末字節(jié)為換行符
extern u16 USART2_RX_STA; //接收狀態(tài)標(biāo)記
void uart2_init(u32 bound);
#define USART3_REC_LEN 200 //定義最大接收字節(jié)數(shù) 200
#define EN_USART3_RX 1 //使能(1)/禁止(0)串口2接收
extern u8 USART3_RX_BUF[USART3_REC_LEN]; //接收緩沖,最大USART_REC_LEN個字節(jié).末字節(jié)為換行符
extern u16 USART3_RX_STA; //接收狀態(tài)標(biāo)記
void uart3_init(u32 bound);
#endif
main.c
#include "stm32f10x.h" // Device header
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "sys.h"
int main()
{
// u8 i = 0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 設(shè)置中斷優(yōu)先級分組2
uart1_init(115200); //串口1初始化波特率為115200
uart2_init(115200); //串口2初始化波特率為115200
uart3_init(115200); //串口3初始化波特率為115200
delay_init(50); //延時初始化
LED_Init(); //初始化LED燈
LED = 0; //關(guān)閉led燈
while(1)
{
if(USART1_RX_STA&0x8000)
{
printf("串口1:我接收到了串口數(shù)據(jù):%s\r\n",USART1_RX_BUF);
USART1_RX_STA = 0;
}
if(USART2_RX_STA&0x8000)
{
LED = 0; //開啟led燈
USART2_RX_STA = 0;
}
if(USART3_RX_STA&0x8000)
{
LED = 1; //關(guān)閉led燈
USART3_RX_STA = 0;
}
delay_ms(500);
}
return 0;
}
????????想顯示接收的數(shù)據(jù),就將標(biāo)準(zhǔn)庫單片機的UART_TX接到CH340的RX上,隨后將CH340的VCC,GND接好,插在電腦上,用串口助手查看數(shù)據(jù)。文章來源地址http://www.zghlxwxcb.cn/news/detail-739942.html
到了這里,關(guān)于使用標(biāo)準(zhǔn)庫和HAL庫的STM32單片機進(jìn)行串口通信/解決因例程為HAL庫的傳感器,而其他模塊都是標(biāo)準(zhǔn)庫,需要將數(shù)據(jù)用串口傳送給標(biāo)準(zhǔn)庫的單片機的相關(guān)問題的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!