上位机串口与stm32串口通信时,上位机打开串口,单片机就死机的问题

一句话概述:
现象:电脑通过usb转串口与stm32串口通信,每当电脑打开串口,stm32就跑飞,给人的感觉就是死机了。
原因:单片机的串口使用的是CH340的TLL转USB,其DTR管脚连接者mcu的复位。一旦上位机开启 了DTR,就会造成MCU复位,给人一种mcu死机的假象。
解决办法:上位机打开串口时,关闭DTR和RTS

1 问题现象

电脑通过usb转串口与stm32串口通信,每当电脑打开串口,stm32就跑飞,给人的感觉就是死机了。

2 操作情况

2.1 上位机open串口代码

使用VC2010开发环境,纯C语言写的上位机串口工具。

HANDLE open_port(int num)
{
	int err;
	DCB dcb;
	HANDLE hPort;
	TCHAR name[30];

	// 打开串口
	if (num == -1)
		num = get_port();
	_sntprintf_s(name, _countof(name), _countof(name), TEXT("\\\\.\\COM%d"), num);
	hPort = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
	if (hPort == INVALID_HANDLE_VALUE)
	{
		return INVALID_HANDLE_VALUE;
	}
	// 设置波特率
	dcb.DCBlength = sizeof(DCB);
	GetCommState(hPort, &dcb);
	dcb.BaudRate = CBR_115200;
	dcb.ByteSize = 8;
	dcb.Parity = NOPARITY;
	dcb.StopBits = ONESTOPBIT;
	dcb.fRtsControl = RTS_CONTROL_ENABLE;
    dcb.fDtrControl = DTR_CONTROL_ENBALE;
	SetCommState(hPort, &dcb);

	lastopen = GetTickCount();
	return hPort;
}

2.2 stm32 usb转串口图

在这里插入图片描述

2.2 stm32串口代码

void USART1_Init(u32 bound)
{
   //GPIO端口设置
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	 //打开时钟
	
	/*  配置GPIO的模式和IO口 */
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX			   //串口输出PA9
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;	    //复用推挽输出
	GPIO_Init(GPIOA,&GPIO_InitStructure);  /* 初始化串口输入IO */
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX			 //串口输入PA10
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;		  //模拟输入
	GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化GPIO */
	
   //USART1 初始化设置
	USART_InitStructure.USART_BaudRate = bound;//波特率设置
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	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(USART1, &USART_InitStructure); //初始化串口1
	USART_Cmd(USART1, ENABLE);  //使能串口1 
	USART_ClearFlag(USART1, USART_FLAG_TC);
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断
	//Usart1 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器	
}

// USART1中断函数
void USART1_IRQHandler(void)                	//串口1中断服务程序
{
	u8 r;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断
	{
		r = USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据
	 	QueueIn(&g_UpdataRxBuff, r);
	}
}

3 定位过程

说起来串口是很简单的协议,最容易想到的就是TX,RX,GND连线。这些就算错误也不至于导致mcu死机。而且上位机还未开始向下位机发送数据,所以也不可能是单片机串口中断出的问题。仅仅是上位机open串口就已经死机了。

按照此思路想到了下位机的USB转串口这部分,仔细看了这部分电路发现了CH340的DTR管脚连到了mcu的reset管脚,这个嫌疑就大了。

立马去查看上位机打开串口的代码,果然配置串口参数的时候使能了DTR。到这里基本就定位了
在这里插入图片描述

4 解决问题

上位机在open串口时,不要使能串口的DTR,这样就不会导致mcu reset管脚被置位。
解决问题后的上位机代码

HANDLE open_port(int num)
{
	int err;
	DCB dcb;
	HANDLE hPort;
	TCHAR name[30];

	// 打开串口
	if (num == -1)
		num = get_port();
	_sntprintf_s(name, _countof(name), _countof(name), TEXT("\\\\.\\COM%d"), num);
	hPort = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
	if (hPort == INVALID_HANDLE_VALUE)
	{
		return INVALID_HANDLE_VALUE;
	}

	// 设置波特率
	dcb.DCBlength = sizeof(DCB);
	GetCommState(hPort, &dcb);
	dcb.BaudRate = CBR_115200;
	dcb.ByteSize = 8;
	dcb.Parity = NOPARITY;
	dcb.StopBits = ONESTOPBIT;
	dcb.fRtsControl = RTS_CONTROL_DISABLE;  // 关闭RTS
    dcb.fDtrControl = DTR_CONTROL_DISABLE;  // 关闭DTR
	SetCommState(hPort, &dcb);

	lastopen = GetTickCount();
	return hPort;
}

遇到问题不要慌,理清思路很重要,机器永远是机器,按照正确的理论查下去,问题一定能解决!!!

需要上位机与下位机串口通信代码的,可以私信我,免费发给你。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值