• 回复
  • 收藏
  • 点赞
  • 分享
  • 发新帖

多个串口的stm32控制

串口是我们常用的一个数据传输接口,STM32F103系列单片机共有5个串口,其中1-3是通用同步/异步串行接口USART(Universal Synchronous/Asynchronous Receiver/Transmitter),4,、5是通用异步串行接口UART(Universal Asynchronous Receiver/Transmitter)。

配置串口包括三部分内容:

1. I/O口配置:TXD配置为复用推挽输出(GPIO_Mode_AF_PP),RXD配置为浮空输入(GPIO_Mode_IN_FLOATING);

2. 串口配置:波特率等;

3. 中断向量配置:一般用中断方式接收数据。

注意事项:

1. USART1是挂在APB2,使能时钟命令为:RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE );其他几个则挂在APB1上,如2口:RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE );

  1. 配置4口和5口的时候,中断名为UART4、UART5,
  2. 中断入口分别为UART4_IRQn、UART5_IRQn
  3. 对应的中断服务函数为void UART4_IRQHandler(void)和void UART5_IRQHandler(void)。

下面是5个串口的配置函数和收发数据函数代码:

#include "stm32f10x.h"

#include "misc.h"

#include "stm32f10x_gpio.h"

#include "stm32f10x_usart.h"

void USART1_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

USART_InitTypeDef USART_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE );

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE );

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //USART1 TX;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure); //端口A;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //USART1 RX;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入;

GPIO_Init(GPIOA, &GPIO_InitStructure); //端口A;

USART_InitStructure.USART_BaudRate = 9600; //波特率;

USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位8位;

USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位1位;

USART_InitStructure.USART_Parity = USART_Parity_No ; //无校验位;

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控;

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式;

USART_Init(USART1, &USART_InitStructure); //配置串口参数;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断组,4位抢占优先级,4位响应优先级;

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //中断号;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

USART_Cmd(USART1, ENABLE); //使能串口;

}

void USART1_Send_Byte(u8 Data) //发送一个字节;

{

USART_SendData(USART1,Data);

while( USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET );

}

void USART1_Send_String(u8 *Data) //发送字符串;

{

while(*Data)

USART1_Send_Byte(*Data++);

}

void USART1_IRQHandler(void) //中断处理函数;

{

u8 res;

if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET) //判断是否发生中断;

{

USART_ClearFlag(USART1, USART_IT_RXNE); //清除标志位;

res=USART_ReceiveData(USART1); //接收数据;

USART1_Send_Byte(res); //用户自定义;

}

}

这是串口2

void USART2_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

USART_InitTypeDef USART_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE );

RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE );

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //USART2 TX;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure); //端口A;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //USART2 RX;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入;

GPIO_Init(GPIOA, &GPIO_InitStructure); //端口A;

USART_InitStructure.USART_BaudRate = 9600; //波特率;

USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位8位;

USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位1位;

USART_InitStructure.USART_Parity = USART_Parity_No ; //无校验位;

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控;

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式;

USART_Init(USART2, &USART_InitStructure); //配置串口参数;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断组,4位抢占优先级,4位响应优先级;

NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //中断号;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

USART_Cmd(USART2, ENABLE); //使能串口;

}

void USART2_Send_Byte(u8 Data) //发送一个字节;

{

USART_SendData(USART2,Data);

while( USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET );

}

void USART2_Send_String(u8 *Data) //发送字符串;

{

while(*Data)

USART2_Send_Byte(*Data++);

}

void USART2_IRQHandler(void) //中断处理函数;

{

u8 res;

if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET) //判断是否发生中断;

{

USART_ClearFlag(USART2, USART_IT_RXNE); //清除标志位;

res=USART_ReceiveData(USART2); //接收数据;

USART2_Send_Byte(res); //用户自定义;

}

}

这是串口3

void USART3_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

USART_InitTypeDef USART_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );

RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE );

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //USART3 TX;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure); //端口A;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //USART3 RX;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入;

GPIO_Init(GPIOB, &GPIO_InitStructure); //端口A;

USART_InitStructure.USART_BaudRate = 9600; //波特率;

USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位8位;

USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位1位;

USART_InitStructure.USART_Parity = USART_Parity_No ; //无校验位;

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控;

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式;

USART_Init(USART3, &USART_InitStructure); //配置串口参数;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断组,4位抢占优先级,4位响应优先级;

NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; //中断号;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);

USART_Cmd(USART3, ENABLE); //使能串口;

}

void USART3_Send_Byte(u8 Data) //发送一个字节;

{

USART_SendData(USART3,Data);

while( USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET );

}

void USART3_Send_String(u8 *Data) //发送字符串;

{

while(*Data)

USART3_Send_Byte(*Data++);

}

void USART3_IRQHandler(void) //中断处理函数;

{

u8 res;

if(USART_GetITStatus(USART3, USART_IT_RXNE) == SET) //判断是否发生中断;

{

USART_ClearFlag(USART3, USART_IT_RXNE); //清除标志位;

res=USART_ReceiveData(USART3); //接收数据;

USART3_Send_Byte(res); //用户自定义;

}

}

这是串口4

void USART4_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

USART_InitTypeDef USART_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE );

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART4, ENABLE );

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //USART4 TX;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOC, &GPIO_InitStructure); //端口A;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //USART4 RX;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入;

GPIO_Init(GPIOC, &GPIO_InitStructure); //端口A;

USART_InitStructure.USART_BaudRate = 9600; //波特率;

USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位8位;

USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位1位;

USART_InitStructure.USART_Parity = USART_Parity_No ; //无校验位;

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控;

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式;

USART_Init(USART4, &USART_InitStructure); //配置串口参数;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断组,4位抢占优先级,4位响应优先级;

NVIC_InitStructure.NVIC_IRQChannel = USART4_IRQn; //中断号;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

USART_ITConfig(USART4, USART_IT_RXNE, ENABLE);

USART_Cmd(USART4, ENABLE); //使能串口;

}

void USART4_Send_Byte(u8 Data) //发送一个字节;

{

USART_SendData(USART4,Data);

while( USART_GetFlagStatus(USART4, USART_FLAG_TC) == RESET );

}

void USART4_Send_String(u8 *Data) //发送字符串;

{

while(*Data)

USART4_Send_Byte(*Data++);

}

void USART4_IRQHandler(void) //中断处理函数;

{

u8 res;

if(USART_GetITStatus(USART4, USART_IT_RXNE) == SET) //判断是否发生中断;

{

USART_ClearFlag(USART4, USART_IT_RXNE); //清除标志位;

res=USART_ReceiveData(USART4); //接收数据;

USART4_Send_Byte(res); //用户自定义;

}

}

这是串口5

void USART5_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

USART_InitTypeDef USART_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD, ENABLE );

RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE );

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //USART5 TX;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOC, &GPIO_InitStructure); //端口A;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //USART5 RX;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入;

GPIO_Init(GPIOD, &GPIO_InitStructure); //端口A;

USART_InitStructure.USART_BaudRate = 9600; //波特率;

USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位8位;

USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位1位;

USART_InitStructure.USART_Parity = USART_Parity_No ; //无校验位;

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控;

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式;

USART_Init(USART5, &USART_InitStructure); //配置串口参数;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断组,4位抢占优先级,4位响应优先级;

NVIC_InitStructure.NVIC_IRQChannel = USART5_IRQn; //中断号;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

USART_ITConfig(USART5, USART_IT_RXNE, ENABLE);

USART_Cmd(USART5, ENABLE); //使能串口;

}

void USART5_Send_Byte(u8 Data) //发送一个字节;

{

USART_SendData(USART5,Data);

while( USART_GetFlagStatus(USART5, USART_FLAG_TC) == RESET );

}

void USART5_Send_String(u8 *Data) //发送字符串;

{

while(*Data)

USART5_Send_Byte(*Data++);

}

void USART5_IRQHandler(void) //中断处理函数;

{

u8 res;

if(USART_GetITStatus(USART5, USART_IT_RXNE) == SET) //判断是否发生中断;

{

USART_ClearFlag(USART5, USART_IT_RXNE); //清除标志位;

res=USART_ReceiveData(USART5); //接收数据;

USART5_Send_Byte(res); //用户自定义;

}

}

全部回复(21)
正序查看
倒序查看
2021-03-23 12:24
STM32确实很强大,5个串口这在51单 片 机时代想都不感想,合理运用串口采集不同的数据,现在为了方便,屏幕都用了串口屏,再加上位机通迅,数据采集也用串口,51单 串口无法满足,只能强大的STM32能满足,而且现在价格也下降了不少,性价比较高。
0
回复
2021-03-23 12:46
@ZH电子达人
STM32确实很强大,5个串口这在51单片机时代想都不感想,合理运用串口采集不同的数据,现在为了方便,屏幕都用了串口屏,再加上位机通迅,数据采集也用串口,51单串口无法满足,只能强大的STM32能满足,而且现在价格也下降了不少,性价比较高。
是的,多串口多任务
0
回复
dog41
LV.6
4
2021-03-23 16:25
厉害
0
回复
荧火
LV.4
5
2021-03-23 16:55
兄弟,码太乱了。
0
回复
2021-03-23 21:53
分享的东西不错,代码有点乱了。。。
0
回复
JacobL
LV.4
7
2021-03-23 23:07
现在32太贵了
0
回复
飞翔2004
LV.10
8
2021-03-24 13:49
现在STM32贵了不少,是用HAL库写的吗?多串口是同时工作的?讲讲原理?
0
回复
boy59
LV.9
9
2021-03-24 16:06

#include "stm32f10x.h"
#include "misc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_usart.h" 

void USART1_Configuration(void)
{ 
  GPIO_InitTypeDef GPIO_InitStructure;   
  USART_InitTypeDef USART_InitStructure;   
  NVIC_InitTypeDef NVIC_InitStructure;        
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE );  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE );
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;             //USART1 TX;  
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;       //复用推挽输出;   
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
  GPIO_Init(GPIOA, &GPIO_InitStructure);                //端口A;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;            //USART1 RX;   
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入;  
  GPIO_Init(GPIOA, &GPIO_InitStructure);                //端口A;
  USART_InitStructure.USART_BaudRate = 9600;           //波特率;   
  USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位8位;    
  USART_InitStructure.USART_StopBits = USART_StopBits_1;   //停止位1位;    
  USART_InitStructure.USART_Parity = USART_Parity_No ;      //无校验位;   
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;    //无硬件流控;   
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;      //收发模式;   
  USART_Init(USART1, &USART_InitStructure);                //配置串口参数;
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);       //设置中断组,4位抢占优先级,4位响应优先级;
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;          //中断号;   
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级;   
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;     //响应优先级;   
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    
  NVIC_Init(&NVIC_InitStructure);
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);   
  USART_Cmd(USART1, ENABLE);                             //使能串口;
}

void USART1_Send_Byte(u8 Data) //发送一个字节;
{  
 USART_SendData(USART1,Data);   
 while( USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET );
}

void USART1_Send_String(u8 *Data) //发送字符串;
{   
  while(*Data)    
  USART1_Send_Byte(*Data++);
}

void USART1_IRQHandler(void) //中断处理函数;
{ 
  u8 res;       
 if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET) //判断是否发生中断;   
 {  
    USART_ClearFlag(USART1, USART_IT_RXNE);         //清除标志位;        
    res=USART_ReceiveData(USART1);                  //接收数据;           
    USART1_Send_Byte(res);                          //用户自定义;   
  }  
}
右上角有个插入程序代码的,似乎可以保留原书写格式。 
0
回复
k6666
LV.9
10
2021-03-24 16:20
@boy59
#include"stm32f10x.h"#include"misc.h"#include"stm32f10x_gpio.h"#include"stm32f10x_usart.h"voidUSART1_Configuration(void){GPIO_InitTypeDefGPIO_InitStructure;USART_InitTypeDefUSART_InitStructure;NVIC_InitTypeDefNVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//USART1TX;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);//端口A;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//USART1RX;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入;GPIO_Init(GPIOA,&GPIO_InitStructure);//端口A;USART_InitStructure.USART_BaudRate=9600;//波特率;USART_InitStructure.USART_WordLength=USART_WordLength_8b;//数据位8位;USART_InitStructure.USART_StopBits=USART_StopBits_1;//停止位1位;USART_InitStructure.USART_Parity=USART_Parity_No;//无校验位;USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//无硬件流控;USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//收发模式;USART_Init(USART1,&USART_InitStructure);//配置串口参数;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断组,4位抢占优先级,4位响应优先级;NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;//中断号;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级;NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;//响应优先级;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_Init(&NVIC_InitStructure);USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);USART_Cmd(USART1,ENABLE);//使能串口;}voidUSART1_Send_Byte(u8Data)//发送一个字节;{USART_SendData(USART1,Data);while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);}voidUSART1_Send_String(u8*Data)//发送字符串;{while(*Data)USART1_Send_Byte(*Data++);}voidUSART1_IRQHandler(void)//中断处理函数;{u8res;if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)//判断是否发生中断;{USART_ClearFlag(USART1,USART_IT_RXNE);//清除标志位;res=USART_ReceiveData(USART1);//接收数据;USART1_Send_Byte(res);//用户自定义;}}右上角有个插入程序代码的,似乎可以保留原书写格式。
楼主这个代码注释比较少,看着比较规范。成熟的函数配置模块。
0
回复
yujunice
LV.5
11
2021-03-24 17:35

串口设置的一般步骤可以总结为如下几个步骤:

1)串口时钟使能,GPIO时钟使能

2)串口复位

3) GPIO端口模式设置

4)串口参数初始化

5)开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)

6)使能串口

7)编写中断处理函数

注:对于复用功能的IO,我们首先要使能GPIO时钟,然后使能复用功能时钟,同时要把GPIO模式设置为复用功能对应的模式。

0
回复
2021-03-25 10:22
@boy59
#include"stm32f10x.h"#include"misc.h"#include"stm32f10x_gpio.h"#include"stm32f10x_usart.h"voidUSART1_Configuration(void){GPIO_InitTypeDefGPIO_InitStructure;USART_InitTypeDefUSART_InitStructure;NVIC_InitTypeDefNVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//USART1TX;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);//端口A;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//USART1RX;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入;GPIO_Init(GPIOA,&GPIO_InitStructure);//端口A;USART_InitStructure.USART_BaudRate=9600;//波特率;USART_InitStructure.USART_WordLength=USART_WordLength_8b;//数据位8位;USART_InitStructure.USART_StopBits=USART_StopBits_1;//停止位1位;USART_InitStructure.USART_Parity=USART_Parity_No;//无校验位;USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//无硬件流控;USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//收发模式;USART_Init(USART1,&USART_InitStructure);//配置串口参数;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断组,4位抢占优先级,4位响应优先级;NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;//中断号;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级;NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;//响应优先级;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_Init(&NVIC_InitStructure);USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);USART_Cmd(USART1,ENABLE);//使能串口;}voidUSART1_Send_Byte(u8Data)//发送一个字节;{USART_SendData(USART1,Data);while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);}voidUSART1_Send_String(u8*Data)//发送字符串;{while(*Data)USART1_Send_Byte(*Data++);}voidUSART1_IRQHandler(void)//中断处理函数;{u8res;if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)//判断是否发生中断;{USART_ClearFlag(USART1,USART_IT_RXNE);//清除标志位;res=USART_ReceiveData(USART1);//接收数据;USART1_Send_Byte(res);//用户自定义;}}右上角有个插入程序代码的,似乎可以保留原书写格式。
我弄了几次一直乱码,我再试试
0
回复
2021-03-25 10:38
@飞翔2004
现在STM32贵了不少,是用HAL库写的吗?多串口是同时工作的?讲讲原理?
标准库
0
回复
2021-03-25 11:27
@荧火
兄弟,码太乱了。
代码这块,已非常完整,可以直接移植
0
回复
2021-03-25 11:27
@zhanceshen
分享的东西不错,代码有点乱了。。。
代码这块,已非常完整,可以直接移植
0
回复
fjfhjmh
LV.9
16
2021-03-25 11:45
厉害了,兄弟
0
回复
2021-03-25 13:13
@yujunice
串口设置的一般步骤可以总结为如下几个步骤:1)串口时钟使能,GPIO时钟使能2)串口复位3)GPIO端口模式设置4)串口参数初始化5)开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)6)使能串口7)编写中断处理函数注:对于复用功能的IO,我们首先要使能GPIO时钟,然后使能复用功能时钟,同时要把GPIO模式设置为复用功能对应的模式。
非常不错
0
回复
2021-03-25 13:35
@fjfhjmh
厉害了,兄弟

上面是5个串口的基本配置

下面主要说实战中串口如何接受

在嵌入式应用中,串口通讯应用几乎是必须的,非常常用,好多事件都是和串口有关,做好串口的数据处理是非常关键的一步,这里再分享一下如何在裸机中对串口数据的有效处理,比如一包数据0xaa,0x55,0xXX,0xXX,0x0a,0x0d,简单介绍串口处理的方法


一.直接在接受中断中判断数据
先定义一个uint8_t Buff和一个uint8_t Table[10];
在接收中断函数里用HAL_UART_Receive_IT(&UART1_Handler, &Buff, 1)这个函数,
每次在中断里面都判断Buff是不是0xaa,如果是则将数据存入到Table[0]中且继续接收下面的数据,都存入到Table的数组中,如果不是则继续进行判断。然后对Table进行判断,首先判断Table[0]和Table[1]分别为0xaa,0x55后,在进行判断Table[4]和Table[5]分别为0x0a,0x0d。在进行判断校验是否正确,正确后取出Table[2]的数据进行处理。
这种方法在数据传输慢的情况下,比较简单方便,还可以,但是在数据快的时候,非常容易造成数据的丢失,还有就是要是第一次数据接收错误,回不到初始化状态,必须复位操作
二.FIFO方式 超时接受
接收中断函数里用HAL_UART_Receive_IT(&UART1_Handler, &Buff, 1)这个函数
接收数据的时候不要做数据处理,而是忠实地接收原始字节流,只管接受入列,就是接受完数据0xaa,0x55,0xXX,0xXX,0x0a,0x0d后,超时时间RxTimeOut3到以后再对数据处理
/* 数据入队 */
chfifo_in(&RxFifo, &Buff);
/* 清零超时 */
RxTimeOut3 = 0;
三.DMA+空闲中断
0、开启串口DMA接收
1、串口收到数据,DMA不断传输数据到存储buf
2、一帧数据发送完毕,串口暂时空闲,触发串口空闲中断
3、在中断服务函数中,可以计算刚才收到了多少个字节的数据
4、解码存储buf,清除标志位,开始下一帧接收

就是接收到一帧数据0xaa,0x55,0xXX,0xXX,0x0a,0x0d后才触发中断接受,处理数据非常高效。


简单总结

健壮的串口接受程序注意几点



1.对于没有dma和空闲中断功能的单片机,最好采用环形队列+超时的方法,保证不会出现丢帧等串口问题,对于那种串口接受,比如接受数据的同时判断解析数据的话,肯定会出问题的


2.对于具备dma和空闲中断功能的单片机,建议采用DMA+空闲中断的方法,帧接受中断,效率非常高,对于不等长的数据非常方便。

3.对于串口设备初始化后最好延时一段时间,时间具体情况而定

0
回复
1260086278
LV.2
19
2021-04-01 16:59
我做通讯一般都加上校验,加和或者CRC校验,不然用起来不放心
0
回复
dy-blNlwnWV
LV.1
20
2021-04-03 09:23
@lihui710884923
上面是5个串口的基本配置下面主要说实战中串口如何接受在嵌入式应用中,串口通讯应用几乎是必须的,非常常用,好多事件都是和串口有关,做好串口的数据处理是非常关键的一步,这里再分享一下如何在裸机中对串口数据的有效处理,比如一包数据0xaa,0x55,0xXX,0xXX,0x0a,0x0d,简单介绍串口处理的方法一.直接在接受中断中判断数据先定义一个uint8_tBuff和一个uint8_tTable[10];在接收中断函数里用HAL_UART_Receive_IT(&UART1_Handler,&Buff,1)这个函数,每次在中断里面都判断Buff是不是0xaa,如果是则将数据存入到Table[0]中且继续接收下面的数据,都存入到Table的数组中,如果不是则继续进行判断。然后对Table进行判断,首先判断Table[0]和Table[1]分别为0xaa,0x55后,在进行判断Table[4]和Table[5]分别为0x0a,0x0d。在进行判断校验是否正确,正确后取出Table[2]的数据进行处理。这种方法在数据传输慢的情况下,比较简单方便,还可以,但是在数据快的时候,非常容易造成数据的丢失,还有就是要是第一次数据接收错误,回不到初始化状态,必须复位操作二.FIFO方式超时接受接收中断函数里用HAL_UART_Receive_IT(&UART1_Handler,&Buff,1)这个函数接收数据的时候不要做数据处理,而是忠实地接收原始字节流,只管接受入列,就是接受完数据0xaa,0x55,0xXX,0xXX,0x0a,0x0d后,超时时间RxTimeOut3到以后再对数据处理/*数据入队*/chfifo_in(&RxFifo,&Buff);/*清零超时*/RxTimeOut3=0;三.DMA+空闲中断0、开启串口DMA接收1、串口收到数据,DMA不断传输数据到存储buf2、一帧数据发送完毕,串口暂时空闲,触发串口空闲中断3、在中断服务函数中,可以计算刚才收到了多少个字节的数据4、解码存储buf,清除标志位,开始下一帧接收就是接收到一帧数据0xaa,0x55,0xXX,0xXX,0x0a,0x0d后才触发中断接受,处理数据非常高效。简单总结健壮的串口接受程序注意几点1.对于没有dma和空闲中断功能的单片机,最好采用环形队列+超时的方法,保证不会出现丢帧等串口问题,对于那种串口接受,比如接受数据的同时判断解析数据的话,肯定会出问题的2.对于具备dma和空闲中断功能的单片机,建议采用DMA+空闲中断的方法,帧接受中断,效率非常高,对于不等长的数据非常方便。3.对于串口设备初始化后最好延时一段时间,时间具体情况而定
这才是串口通讯实战的经验总结,非常感谢
0
回复
2021-04-07 11:25
@1260086278
我做通讯一般都加上校验,加和或者CRC校验,不然用起来不放心
校验是通信协议这块,现在主要分析如何让接受这块
0
回复
2021-04-07 11:30
@飞翔2004
现在STM32贵了不少,是用HAL库写的吗?多串口是同时工作的?讲讲原理?
多串口工作,一是中断,二是时间轮询,三是实时操作系统
0
回复