历史上的今天
返回首页

历史上的今天

今天是:2024年10月28日(星期一)

正在发生

2019年10月28日 | STM32F103RC USART2串口查询方式接收数据

2019-10-28 来源:eefocus

现有一个小需求,使用STM32F1系列单片机做串口2的收发数据的功能,通过PC上的串口调试助手给单片机发一串数据,单片机收到数据后再给PC的串口调试助手发回去。


看似简单的功能,调试了好久才调好,记录一下供大家参考。


STM32使用USART2,对应单片机的PA1控制方向,PA2发送,PA3接收。


代码如下:


z_hardware_usart2.h


#ifndef __STM32F10X_H

#define __STM32F10X_H

#include "stm32f10x.h"

#endif

 

#ifndef __Z_UTIL_TIME_H

#define __Z_UTIL_TIME_H

#include "z_util_time.h"

#endif

 

#ifndef _UART_BUF_LEN_512

#define _UART_BUF_LEN_512 512

#endif

 

#ifndef _UART_BUF_LEN_256

#define _UART_BUF_LEN_256 256

#endif

 

#ifndef _UART_COMM_CH_TIMEOUT_3MS

#define _UART_COMM_CH_TIMEOUT_3MS 3

#endif

 

#ifndef _UART_COMM_CH_TIMEOUT_2MS

#define _UART_COMM_CH_TIMEOUT_2MS 2

#endif

 

#ifndef _UART_COMM_INT_TIMEOUT_300MS

#define _UART_COMM_INT_TIMEOUT_300MS 300

#endif

 

#ifndef _UART_COMM_INT_TIMEOUT_500MS

#define _UART_COMM_INT_TIMEOUT_500MS 500

#endif

 

void init_hardware_usart2(u32 bound);

void func_usart2_send_a_byte(u8 abyte);

u8 func_usart2_recv_a_byte(u8 *recv_data);

void func_usart2_send_bytes(u8 *bytes, u8 bytes_len);

u8 func_usart2_recv_bytes(const u16 BUF_MAX_LEN, u8 *recv_datas, u16 *recv_datas_len, const u16 int_timeout_ms, const u8 ch_timeout_ms);

z_hardware_usart2.c


#ifndef __Z_HARDWARE_USART2_H

#define __Z_HARDWARE_USART2_H

#include "z_hardware_usart2.h"

#endif

 

void init_hardware_usart2(u32 bound)

{

GPIO_InitTypeDef GPIO_InitStructure;

USART_InitTypeDef USART_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(GPIOA, &GPIO_InitStructure);

 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_Init(GPIOA, &GPIO_InitStructure);

 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_Init(GPIOA, &GPIO_InitStructure);

USART_InitStructure.USART_BaudRate = bound;

USART_InitStructure.USART_WordLength = USART_WordLength_8b;

USART_InitStructure.USART_StopBits = USART_StopBits_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);

USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);

USART_Cmd(USART2, ENABLE);

USART_ClearFlag(USART2, USART_FLAG_TC);

GPIO_ResetBits(GPIOA, GPIO_Pin_1);

}

 

void func_usart2_send_a_byte(u8 abyte)

{

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

USART_SendData(USART2, abyte);

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

}

 

u8 func_usart2_recv_a_byte(u8 *recv_data)

{

if(USART_GetFlagStatus(USART2, USART_FLAG_RXNE) != RESET)

{

*recv_data = USART_ReceiveData(USART2);

USART_ClearFlag(USART2, USART_FLAG_RXNE);

return 0;

}

return 1;

}

 

void func_usart2_send_bytes(u8 *bytes, u8 bytes_len)

{

u8 i;

GPIO_SetBits(GPIOA, GPIO_Pin_1);

for(i = 0; i < bytes_len; i++)

{

func_usart2_send_a_byte(bytes[i]);

}

GPIO_ResetBits(GPIOA, GPIO_Pin_1);

}

 

u8 func_usart2_recv_bytes(const u16 BUF_MAX_LEN, u8 *recv_datas, u16 *recv_datas_len, const u16 int_timeout_ms, const u8 ch_timeout_ms)

{

u8 flag_recv;

u8 tmp_recv;

u16 tmp_int_timeout_cnt = 0;

u8 tmp_ch_timeout_cnt = 0;

u16 len_recv = 0;

u8 *p_recv;

p_recv = recv_datas;

GPIO_ResetBits(GPIOA, GPIO_Pin_1);

for(;func_usart2_recv_a_byte(&tmp_recv) != 0;)

{

tmp_int_timeout_cnt ++;

if(tmp_int_timeout_cnt > int_timeout_ms * 10)

{

return 1;

}

delay_us(100);

}

len_recv ++;

*p_recv = tmp_recv;

p_recv ++;

for(;;)

{

flag_recv = func_usart2_recv_a_byte(&tmp_recv);

if(flag_recv == 0)//data recv

{

tmp_ch_timeout_cnt = 0;

len_recv ++;

*p_recv = tmp_recv;

p_recv ++;

}

else //data not recv

{

tmp_ch_timeout_cnt ++;

delay_us(800);//FIXME 适用9600波特率。波特率不同需要针对性修改

}

if(tmp_ch_timeout_cnt > ch_timeout_ms)

{

*recv_datas_len = len_recv;

return 0;

}

if(len_recv > BUF_MAX_LEN - 1)

{

*recv_datas_len = BUF_MAX_LEN - 1;

return 2;

}

}

}

z_util_time.h


#ifndef __STM32F10X_H

#define __STM32F10X_H

#include "stm32f10x.h"

#endif

 

#define AHB_INPUT 72

 

void delay_us(uint32_t time_us);

void delay_ms(uint32_t time_ms);

z_util_time.c


#ifndef __Z_UTIL_TIME_H

#define __Z_UTIL_TIME_H

#include "z_util_time.h"

#endif

 

void delay_us(uint32_t time_us)

{

SysTick->LOAD = AHB_INPUT * time_us;

SysTick->VAL = 0x00;

SysTick->CTRL = 0x00000005;

for(;!(SysTick->CTRL & 0x00010000););

SysTick->CTRL = 0x00000004;

}

 

void delay_ms(uint32_t time_ms)

{

for(;time_ms-- > 0;)

{

delay_us(1000);

}

}

main.c


#include "stm32f10x.h"

 

#ifndef __Z_HARDWARE_USART2_H

#define __Z_HARDWARE_USART2_H

#include "z_hardware_usart2.h"

#endif

 

#include

 

int main()

{

u8 to_recv[_UART_BUF_LEN_256];

u16 to_recv_len;

init_hardware_usart2(9600);

while (1)

{

if(func_usart2_recv_bytes(_UART_BUF_LEN_256, to_recv, &to_recv_len, _UART_COMM_INT_TIMEOUT_500MS, _UART_COMM_CH_TIMEOUT_3MS) == 0)

{

func_usart2_send_bytes(to_recv, to_recv_len);

}

to_recv_len = 0;

memset(to_recv, 0, sizeof(to_recv));

}

}

效果如下:

经过测试发现,串口调试助手给单片机发送了1W+多次,失误率为0,准确率可以应用。

测试代码,仅供参考。


推荐阅读

史海拾趣

Bivar公司的发展小趣事

在电子行业的竞争中,Bivar公司意识到单打独斗难以取得长久的成功。因此,公司积极寻求与其他企业的合作机会,共同开发新产品、拓展市场。通过与上下游企业的紧密合作,Bivar不仅降低了成本、提高了效率,还获得了更多的资源和支持,进一步巩固了市场地位。

Cosel公司的发展小趣事

随着全球化进程的加速,Cosel公司开始将目光投向国际市场。1990年,公司成立了U.S.ELCO INC.(现名为COSEL U.S.A.,INC.),正式进入美国市场。随后,公司又设立了欧洲常驻办事处,进一步拓展了欧洲市场。这些举措使得Cosel公司的产品和服务能够覆盖更广泛的地区,为公司带来了更多的商机和发展空间。

长运通(CYT)公司的发展小趣事

长运通注重与高校和研究机构的合作,积极引进和培养人才。公司与电子科技大学、西安电子科技大学等知名高校建立了紧密的合作关系,共同开展技术研发和人才培养。通过与高校的合作,长运通不仅获得了更多的技术资源支持,也为公司培养了一批高素质的研发人才。这些人才为公司的发展提供了强有力的支撑。

General Electric Company公司的发展小趣事
在实际应用前进行充分的测试验证,确保电路的稳定性和可靠性。
科山芯创(COSINE)公司的发展小趣事

科山芯创深知品质是企业的生命线。他们建立了严格的质量管理体系,从原材料采购到生产流程再到成品检测,每一个环节都严格把关。同时,他们还不断提升服务水平,为客户提供全方位的技术支持和解决方案。这些努力使得科山芯创在客户中赢得了良好的口碑和信任。

Amerace Electronic Components公司的发展小趣事

随着公司技术的不断提升和产品质量的持续保证,Amerace Electronic Components公司开始积极拓展全球市场。公司通过与国际电子行业的领军企业建立战略合作关系,成功将产品打入国际市场。同时,Amerace还在全球范围内设立了多个生产基地和销售网络,以满足不同国家和地区的客户需求。这种全球化的战略布局使得Amerace在全球电子元件市场中占据了重要地位。

问答坊 | AI 解惑

关于usb device时vbus是否必须连接

在设计一个9b92的板子,请问之前有人用过别的型号的usb 接口的功能么. 但作为usb device用时,是否一定要把vbus上拉。 我的板不从usb去电,是否可以通过软件在上电后启动usb口进行枚举? 因为我想省下vbus那个脚做io :-),LM的脚的复用的也太 ...…

查看全部问答>

那里可以下到魅族M8和宇龙酷派N90手机的原理图啊?想知道他们用的什么手机基带芯片,他们的GSM协议栈怎么实现的。

那里可以下到魅族M8和宇龙酷派N90手机的原理图啊?想知道他们用的什么手机基带芯片,他们的GSM协议栈怎么实现的。…

查看全部问答>

用VerQueryValue得到文件信息的问题

TCHAR *szver=NULL; dwlen=GetFileVersionInfoSize(szpath[k],&dwtemp); szver=new TCHAR[dwlen]; rt1=GetFileVersionInfo(szpath[k],0,dwlen +1,szver);//这里rt1==1了 DWORD cbTranslate = 0; VerQueryValue(szver, TEXT(\"\\\\VarFileInfo\ ...…

查看全部问答>

请问IC设计和嵌入式系统开发哪个更有前景

我刚上大二,对IC设计和嵌入式系统开发都有一定的兴趣,我是读电子的,同时对软件也很感兴趣,所以为了避免茫然,我想定一个长远的目标,从而更好的努力。所以我想知道这两者哪个更有前景呢,说白了就是以后出来哪个薪水相对来说会更高呢。我该如何 ...…

查看全部问答>

西门子300和触摸屏问题

锅炉房的plc300系列有个触摸屏,现在出现个现象,有三个高压泵,2#一直运行中,1#3#备用,现在启动1#泵触摸屏会显示气压极高,导致锅炉停炉,但是起3#就没这种现象,高手们都来分析下,存在干扰?…

查看全部问答>

关于MCS51的特殊寄存器问题

TCON的字节地址是88H,TMOD是89H,而TCON是可位寻址的,也就是说TCON中IE0位地址也是89H,岂不是和TMOD地址重复?…

查看全部问答>

论坛有群吗?

如题。T3论坛有群吗~~作为一个爱好者。希望和大家一起讨论交流。一起学习,共同进步~~…

查看全部问答>

速度性能的应用示例方案——传统的GPIB配置与经过优化的开关-源表配置

吉时利707B型开关主机和2636A型源表的优化配置时获得的速度性能的应用实例方案,有如下2个介绍: 方案1:传统的GPIB配置 此配置如图1所示。与黄色阴影部分的任务相关的时间进行了吞吐能力对比。蓝色阴影部分的执行任务的时间未进行吞吐能力对比 ...…

查看全部问答>

4~20MA电流采集电路参考

现在很多仪表都是4~20MA电流方式进行信号远传,那我们就找到资料电流采集上的一些处理吧! 同时电源处理部分也可以学习下! …

查看全部问答>