STM32F103串口1和串口2不同波特率之间交换数据问题

发布者:脑力风潮最新更新时间:2019-04-12 来源: eefocus关键字:STM32F103  串口  波特率  交换数据 手机看文章 扫描二维码
随时随地手机看文章

前几天写一个东西,要用到STM32F103的串口1和串口2以不同的波特率交换数据,也就是说串口1波特率为9600,串口2波特率为115200,串口1可以把接收到的数据通过串口2发送出去,串口2也可以把接收到的数据通过串口1发送出去。低波特率向高波特率发送数据没问题,高波特率向低波特率发送数据会丢数据,原因是低波特率的串口还没发送完数据高波特率的串口就又发数据过来了,处理不过来。在同事的在帮助下,写出一个先进先出环形队列(FIFO)程序。接收数据用中断,发送数据用在主函数中查询发送完成标志位。希望对大家有点帮助,可能程序不完美,但程序可以用。定义一个fifo.h部件和一个fifo.c文件。其他的都在主函数中调用。


#ifndef _FIFO_H_

#define _FIFO_H_


#include "stm32f10x.h"


#define FIFO_SIZE 256


typedef struct

{

    uint8_t Buf[FIFO_SIZE];    //定义缓冲区,大小用FIFO_SIZE定义

    volatile uint32_t Read;    //定义读取指针

    volatile uint32_t Write;   //定义写入指针

}FIFOTypeDef;


extern FIFOTypeDef USART1_fifo;

extern FIFOTypeDef USART2_fifo;


void PutChar(uint8_t c);

uint8_t GetChar(uint8_t *c);

void PutChar1(uint8_t c);

uint8_t GetChar1(uint8_t *c);


#endif

#include "fifo.h"


FIFOTypeDef USART1_fifo;   //定义串口1的队列fifo

FIFOTypeDef USART2_fifo;   //定义串口2的队列fifo


/*******************************************************************************

* Function Name : PutChar

* Description   : put a fifo value into fifo buffer

* Input         : c

* Output        : None

* Return        : None

*******************************************************************************/

void PutChar(uint8_t c)

{

  USART1_fifo.Buf[USART1_fifo.Write] = c;  //写入数据到缓冲区

  

  if(++USART1_fifo.Write >= FIFO_SIZE)    //写入指针超出缓冲区最大值,返回最初位置

  {

    USART1_fifo.Write = 0;

  }

}


/*******************************************************************************

* Function Name  : GetChar

* Description    : read fifo value from fifo buffer with timeout feature

* Input          : c

* Output         : None

* Return         : 0 

*******************************************************************************/

uint8_t GetChar(uint8_t *c)

{


  if(USART1_fifo.Read == USART1_fifo.Write)   //如果没有存入数据,则返回0

  {

    return 0;

  }

  else

  {

    *c = USART1_fifo.Buf[USART1_fifo.Read]; //读取数据,传入到指针c

    

    if (++USART1_fifo.Read >= FIFO_SIZE) //读取指针超出缓冲区最大值,返回最初位置

    {

      USART1_fifo.Read = 0;

    }


    return 1; //成功读取数据返回1

  }

}


/*******************************************************************************

* Function Name : PutChar

* Description   : put a fifo value into fifo buffer

* Input         : c

* Output        : None

* Return        : None

*******************************************************************************/

void PutChar1(uint8_t c)

{

  USART2_fifo.Buf[USART2_fifo.Write] = c;

  

  if(++USART2_fifo.Write >= FIFO_SIZE)

  {

    USART2_fifo.Write = 0;

  }

}


/*******************************************************************************

* Function Name  : GetChar

* Description    : read fifo value from fifo buffer with timeout feature

* Input          : c

* Output         : None

* Return         : 0 

*******************************************************************************/

uint8_t GetChar1(uint8_t *c)

{


if(USART2_fifo.Read == USART2_fifo.Write)

{

return 0;

}

else

  {

    *c = USART2_fifo.Buf[USART2_fifo.Read];

    

    if (++USART2_fifo.Read >= FIFO_SIZE)

    {

      USART2_fifo.Read = 0;

    }


    return 1;

  }

}




#include "stm32f10x.h"

#include "fifo.h"


/*******************************************************************************

* Function Name : UIF_Init 

* Description   : 初始化串口

* Input         : USARTx = USART1,2,3 

*               : BPS = 1200, 4800,,,

*               : STB = 1,5,2,15

* Return        : None 

*******************************************************************************/

void UIF_Init(USART_TypeDef* USARTx, uint32_t BPS, uint32_t STB)

{

  uint32_t Dly;

  USART_InitTypeDef USART_InitStruct; //定义串口结构体


NVIC_InitTypeDef NVIC_InitStructure; //定义中断结构体


  

USART_ClearFlag(USARTx, USART_FLAG_TC);

USART_DeInit(USARTx);              //复位串口x


USART_InitStruct.USART_BaudRate = BPS;

USART_InitStruct.USART_WordLength = USART_WordLength_8b;  //8位字节长度数据

if(STB == 1)

USART_InitStruct.USART_StopBits = USART_StopBits_1;

else if(STB == 5)

USART_InitStruct.USART_StopBits = USART_StopBits_0_5;

else if(STB == 15)

USART_InitStruct.USART_StopBits = USART_StopBits_1_5;

else

USART_InitStruct.USART_StopBits = USART_StopBits_2;

USART_InitStruct.USART_Parity = USART_Parity_No;         //无奇偶检验位

USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制

USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //接收 发送模式

USART_Init(USARTx, &USART_InitStruct);   //初始化串口x



NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //使能串口1中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占优先级2级

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级2级

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道

NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器


NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //使能串口2中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占优先级2级

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //从优先级2级

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道

NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

 

if(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==SET)

    USART_ClearFlag(USARTx, USART_FLAG_TC);

USART_Cmd(USARTx, ENABLE);          //使能串口x

for(Dly = 0; Dly < 0xFFFF; Dly++);

USART_ClearFlag(USARTx, USART_FLAG_TC); 


USART_ITConfig(USARTx,USART_IT_RXNE,ENABLE);   //开启接收中断

 

}


/*******************************************************************************

* Function Name : GPIO_Config 

* Description   : 初始化IO

* Input         : None 

* Return        : None 

*******************************************************************************/

void GPIO_Config(void)

{

  GPIO_InitTypeDef GPIO_InitStruct;


  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA

                       | RCC_APB2Periph_GPIOB

                       | RCC_APB2Periph_AFIO

                       | RCC_APB2Periph_USART1, ENABLE);

  

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); 


  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;


  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; //USART1_TX Output 

  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;

  GPIO_Init(GPIOA, &GPIO_InitStruct);


  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; //USART1_RX Input  

  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_Init(GPIOA, &GPIO_InitStruct);

  

  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2; //USART2_TX Output   

  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;

  GPIO_Init(GPIOA, &GPIO_InitStruct);


  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3; //USART2_RX Input    

  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_Init(GPIOA, &GPIO_InitStruct);

   

}

/*******************************************************************************

* Function Name : NVIC_Configuration 

* Description   : 设置NVIC中断分组

* Input         : None 

* Return        : None 

*******************************************************************************/

void NVIC_Configuration(void)

{

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

}

/*******************************************************************************

* Function Name : USART_SendByte 

* Description   : 发送一个字节

* Input         : USARTx = USART1,2,3 

    Data = 要发送的数据

* Return        : None 

*******************************************************************************/

void USART_SendByte(USART_TypeDef* USARTx, uint16_t Data)

{

USARTx->DR = (Data & (uint16_t)0x01FF);;

while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) != SET);

}

/*******************************************************************************

* Function Name : main 

* Description   : 主函数

* Input         : None

* Return        : None 

*******************************************************************************/

int main(void)

{

uint8_t byte;

GPIO_Config();

NVIC_Configuration();

UIF_Init(USART1,115200,1); //串口1波特率115200,1位停止位

UIF_Init(USART2,9600,1); //串口2波特主9600,1位停止位 //使能串口

while(1)

{

 

if(USART1_fifo.Write != USART1_fifo.Read) //如果读取指针不等于写入指针,说明缓冲区有数据

{

if(GetChar(&byte)) //如果读取数据成功,返回1

{

USART_SendByte(USART2,byte); //把串口1的缓冲区数据通过串口2发送出去

}

}

if(USART2_fifo.Read!=USART2_fifo.Write)  //如果读取指针不等于写入指针,说明缓冲区有数据

{

if(GetChar1(&byte))   //如果读取数据成功,返回1

{

    USART_SendByte(USART1,byte); //把串口2的缓冲区数据通过串口1发送出去

    }

}

}


/*******************************************************************************

* Function Name : USART1_IRQHandler 

* Description   : 串口1中断服务程序

* Input         : None

* Return        : None 

*******************************************************************************/

void USART1_IRQHandler(void)

{

u8 res; 

  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //如果接收到数据

{

USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清空接收标志

res = USART_ReceiveData(USART1);

PutChar(res);   //压入数据到串口1缓冲区

}


//溢出,如果发生溢出需要先读SR,再读DR寄存器则可清除不断入中断的问题

if(USART_GetFlagStatus(USART1,USART_FLAG_ORE)==SET)

{

USART_ClearFlag(USART1,USART_FLAG_ORE); //读SR其实就是清除标志

USART_ReceiveData(USART1);    //读DR

}

}

/*******************************************************************************

* Function Name : USART2_IRQHandler 

* Description   : 串口2中断服务程序

* Input         : None

* Return        : None 

*******************************************************************************/

void USART2_IRQHandler(void)        

{

u8 Res;


if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //接收中断

{

USART_ClearITPendingBit(USART2,USART_IT_RXNE);//清空接收标志

Res =USART_ReceiveData(USART2);//(USART2->DR); //读取接收到的数据

PutChar1(Res);      //压入数据到串口2缓冲区

    }


//溢出,如果发生溢出需要先读SR,再读DR寄存器则可清除不断入中断的问题

if(USART_GetFlagStatus(USART2,USART_FLAG_ORE)==SET)

{

USART_ClearFlag(USART2,USART_FLAG_ORE); //读SR其实就是清除标志

USART_ReceiveData(USART2);    //读DR

}

关键字:STM32F103  串口  波特率  交换数据 引用地址:STM32F103串口1和串口2不同波特率之间交换数据问题

上一篇:STM32 串口详细讲解
下一篇:STM32F103 SPI3总结

推荐阅读最新更新时间:2024-03-16 16:27

STC89C52RC单片机+串口+红外控制16路舵机程序
只有控制16路舵机的程序,现在发上来提供参考 舵机可以通过串口控制,也可以用红外控制 单片机源程序如下: #include PCA9685_TJ.h #include stdio.h #include math.h /*使用说明: 在main主程序 PCA9685_init(); 在main主程序的while加入 PCA9685_main(); //注: 必需放在UART1_main();的前面 */ #define PCA9685_adrr 0x80// 1+A5+A4+A3+A2+A1+A0+w/r #define PCA9685_SUB
[单片机]
STC89C52RC单片机+<font color='red'>串口</font>+红外控制16路舵机程序
CAN总线波特率计算及设置方法(STM32,SJA1000,LPC2292)
SJA1000 内部频率基准源F_BASE = Fclk/2,即外部晶振频率Fclk的2分频。注意任何应用中,当利用外部晶振作为基准源的时候,都是先经过2分频整形的。 1.1 位周期的组成   波特率(fbit)是指单位时间内所传输的数据位的数量,一般取单位时间为1s。波特率由通信线上传输的一个数据位周期的长度(Tbit)决定,如下式所示。   Fbit=1/Tbit  (1)   根据Philips公司的独立通信控制器,一个位周期由3个部分组成:同步段(tSYNC_SEG)、相位缓冲段1(tTSEG1)和相位缓冲段2(tTSEG2)。   Tbit=tSYNC_SEG+tTSEG1+tTSEG2   (2)   所有这些
[单片机]
STM32F103定时器输入捕获功能
  STM32F103单片机的定时器不仅能输出PWM波,而且还能捕获输入的PWM波。可以通过定时器的捕获功能测量输入PWM波的周期和占空比。   在输入捕获模式下,当检测到ICx信号上相应的边沿后,计数器的当前值被锁存到捕获/比较寄存器(TIMx_CCRx)中。当发生捕获事件时,相应的CCxIF标志(TIMx_SR寄存器)被置1,如果开放了中断或者DMA操作,则将产生中断或者DMA请求。如果发生捕获事件时CCxIF标志已经为高,那么重复捕获标志CCxOF(TIMx_SR寄存器)被置1。写CCxIF=0可清除CCxIF,或读取存储在TIMx_CCRx寄存器中的捕获数据也可清除CCxIF。写CCxOF=0可清除CCxOF。  
[单片机]
8051单片机(STC89C52)以轮询方式实现串口通信(51接收数据后发送回PC端)
#include STC89C5xRC.H int main() { char buf; TMOD = 0x21; //设定timer1的工作模式 SCON = 0x50; //设置串行通信格式 TH1 = 0xE6; //设定timer1的初始值 TL1 = 0xE6; TR1 = 1; //开启timer1 while(1) { if(RI == 1) { //如果收到数据 buf = SBUF; RI = 0; SBUF = buf;//将收到的数据发回去 while(TI == 0); //等待数据发送完毕 TI = 0;
[单片机]
8051单片机(STC89C52)以轮询方式实现<font color='red'>串口</font>通信(51接收<font color='red'>数据</font>后发送回PC端)
Python实现的简单的单片机串口助手程序
项目中遇到需要用电脑通过串口来控制单片机IO口,查询了一些资料,可以使用python来实现简单的串口通信, 所以用python实现了一个简单的单片机串口助手,可以将串口助手发往单片机的字符回传给串口助手。也可以 将配合单片机程序对单片机进行控制。 python实现的串口助手代码如下: import time; #需要调用延时函数 import serial #需要调用串口库 import binascii #需要将传送的字符进行转换 if __name__ == '__main__': ser = serial.Serial(); #生成串口 ser.baudrate = 4800 #设
[单片机]
Python实现的简单的单片机<font color='red'>串口</font>助手程序
STC15串口1\串口2\串口3和串口4源程序
STC15标准程序,有需要的可以参考。 单片机源程序如下: //本程序的功能是串口1串口2串口3和串口4独立接受数据,并将接收到的数据再发送出去 #include STC15W4K32S4.H #include stdio.h #include intrins.h #include stdlib.h #include absacc.h #define uchar unsigned char #define uint unsigned int #define ulong unsigned long uchar idata SendBuf1 , SendBuf2 , SendBuf3 , SendB
[单片机]
基于PowerPC内核MPC565的多串口通信扩展设计
  在一些复杂的控制领域中,控制计算机往往需要与多个终端进行信息的交互通信。但由于工程现场环境的限制和应用设备的日渐增多,近距离集中式的通信管理已不再具有普遍适用性。   随着远程集散控制理念的出现,串行数据通信因其结构简单、设计方便、价格低廉、占用资源少、传输距离远等优势而得到了广泛普及。而近年来串口通信正朝着带宽、速度、稳定性逐渐增加的方向发展,利用多个串口进行信号采集或数据传输为多设备分布式布局提供了可能。但一般的处理器板卡只有一至两个RS232串口,难以满足控制系统对串口数量和数据传输过程中抗干扰性能的要求,因此需要对串口进行扩展设计。   传统的串口扩展设计多以微控制器与串口芯片在板集成的方式实现,需单独设计其控制电路
[嵌入式]
基于串口透明传输的无线射频收发系统设计
目前市场上各类无线产品种类及应用越来越广泛,如何让广大学生、电子研发人员及一些小公司能快速在自己的产品中使用无线技术、降低无线技术的门槛,是本设计的初衷。对一些没有接触无线技术的人,从学到最后的设计应用需要比较长的时间。本文设计了一种基于无线收发芯片Si4432和单片机C8051F340的无线射频收发系统。基于串口透明传输,用户只需要了解一些串口指令即可方便实现无线收发。多种标准接口方便用户把模块嵌入到自己的产品中去。模块经过大量的试验、改进,能实现较远距离的稳定传输。 1、系统总体方案 无线射频收发系统结构框图如图1所示,由单片机C8051F340控制Si4432实现无线数据的收发。 发送模块中的C8051F340将数据
[单片机]
基于<font color='red'>串口</font>透明传输的无线射频收发系统设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved