STM32串口使用小结

        使用STM32的过程中,最常用到的就是串口了。我们经常可以通过串口来打印一下内部变量的值,通过打印来看目前程序的运行状态等,最常用到的还是串口1,尤其是串口1的printf函数,完全兼容C语言的printf,使用起来非常的方便。但是当我们使用的外设较多时,并且好几个外设都需要使用串口进行通信时,只是用串口1,就不足以完成项目的需求。本文主要介绍如何同时使用STM32的三个串口。主要包括

1.如何同时打开串口1 2 3,并且互不干扰。

2.如何通过已打开的串口2 3实现类似于串口1的printf函数的功能。

3.如何连续输出一个十六进制字符数组。

4.如何实现通过串口直接获取一个格式化类型值,比如直接获取一个int值。

本文的测试程序运行在STM32F103C8T6上,采用库函数版本,如果需要移植,请参考博主另一篇文章https://mp.csdn.net/postedit/102093845

1.时钟

        在使用任何外设的时候都需要先知道外设对应的时钟,先将外设的时钟打开,我们先打开Datasheet看一下系统的架构图。从图上可以看出串口1挂载在APB2上,而串口2和串口3挂载在APB1上。打开时钟的操作就是调用库函数即可,例如对于串口1

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);    

即可打开串口1时钟

 

打开串口1 时钟之后,只是打开了串口1的功能,我们还需要打开串口1用来与外界通信的管脚的时钟,也就是IO口的时钟,每一个串口对应的TX和RX管脚在Datasheet中也可以找到,如下所示为串口1的TXD和RXD,从中可看出TXD为PA9,RXD为PA10。我们需要打开GPIOA的时钟,上图中可以看出GPIOB时钟挂在载在APB2上。因此

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);    

即可打开时钟。相应的串口2和串口3的对应管脚在数据手册中也可以找到,相应的如下。

串口2:TXD->PA2  RXD->PA3

串口3:TXD->PB10    RXD->PB11

             

2.管脚的配置

由于对于TXD需要发送数据,因此需要上拉提高输出能力,同时端口的功能为复用功能,因此TXD需要设置成复用上拉模式。

对于RXD需要接收数据,设置成浮空输入即可。串口1的端口初始化如下:

//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;	//复用上拉输出
  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  

 3.串口的配置

串口主要包括波特率,数据位,停止位,校验位的长度,NVIC优先级以及中断等设置。串口1初始化函数如下所示

//Usart1 NVIC
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//初始化NVIC
  
   //USART 初始化

	USART_InitStructure.USART_BaudRate = bound;//波特率
	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); //初始化串口1
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断
  USART_Cmd(USART1, ENABLE);                    //使能串口1

串口2初始化函数如下所示

void uart_init2(u32 bound){
  //GPIO¶Ë¿ÚÉèÖÃ
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//使能时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
  
	//USART2_TX   GPIOA.2
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//¸
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.2
   
  //USART2_RX	  GPIOA.3
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

  //Usart1 NVIC 初始化
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQÍ初始化通道使能
	NVIC_Init(&NVIC_InitStructure);	//NVIC初始化
  

	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, ENABLE);
  USART_Cmd(USART2, ENABLE);                

}

串口3初始化如下:

void uart_init3(u32 bound){
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	
  GPIO_Init(GPIOB, &GPIO_InitStructure);
   
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;		
	NVIC_Init(&NVIC_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(USART3, &USART_InitStructure); 
  USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
  USART_Cmd(USART3, ENABLE); 

}

 4.中断函数

       在上述过程中,我们打开了串口的接受使能,因此需要定义相应的中断响应函数,响应函数中我们每次接受一个字符(这也是我们设置好的,8位数据位,也就是一个字节的数据),同时将数据进行保存,同时在中断函数中要清除中断标志位。

       上述是我们必须做的,目前一些开发板的厂商在中断函数中加入了一些特殊的含义,比如每次检测到换行符(即\r\n)作为一个字符串的结束,也就是每一次必须发送以换行符为结尾的字符串,才被识别为一个字符串。我们必须知道这并不是必须的,程序是自己写的,我们可以接受5个字符串作为一次接受,也可以以aa为结尾这都是可以的。一个最简单的串口接受函数如下:

void USART1_IRQHandler(void)                	
	{
	u8 Res;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //进入接受中断
		{
		Res =USART_ReceiveData(USART1);//读取寄存器中的值
		
			}   		 
     } 

实际中我们可以自己定制,为了方便,本次也采用接受换行符作为结束,相应的串口1的中断函数为

void USART1_IRQHandler(void)                
	{
	u8 Res;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接受中断
		{
		Res =USART_ReceiveData(USART1);	
		
		if((USART_RX_STA&0x8000)==0)//接受没有完成
			{
			if(USART_RX_STA&0x4000)//接收到了0x0d 即\r  
				{
				if(Res!=0x0a)USART_RX_STA=0;//接收到了\r 但是下一个不是\n那么重新接受
				else USART_RX_STA|=0x8000;	//接受到了\n 那么接受结束
				}
			else //没有接收到\r 
				{	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
					{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;//将数据存到USART_RX_BUF这个数组中
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接受的数据超过了预定的长度,重新接受
					}		 
				}
			}   		 
     } 

} 

从上面的程序可以看出,最终\r\n之前的字符串都被保存到了 USART_RX_BUF这个数组中,数组的长度为USART_REC_LEN。

整个usart.c文件的内容如下

#include "sys.h"
#include "usart.h"	  

#if SYSTEM_SUPPORT_OS
#include "includes.h"				  
#endif
 
#if 1
#pragma import(__use_no_semihosting)             
             
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
  
_sys_exit(int x) 
{ 
	x = x; 
} 
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);  
    USART1->DR = (u8) ch;      
	return ch;
}
#endif 

 
 
#if EN_USART1_RX   //Èç¹ûʹÄÜÁ˽ÓÊÕ
//´®¿Ú1ÖжϷþÎñ³ÌÐò
//×¢Òâ,¶ÁÈ¡USARTx->SRÄܱÜÃâĪÃûÆäÃîµÄ´íÎó   	
char USART_RX_BUF[USART_REC_LEN];     //½ÓÊÕ»º³å,×î´óUSART_REC_LEN¸ö×Ö½Ú.
//½ÓÊÕ״̬
//bit15£¬	½ÓÊÕÍê³É±êÖ¾
//bit14£¬	½ÓÊÕµ½0x0d
//bit13~0£¬	½ÓÊÕµ½µÄÓÐЧ×Ö½ÚÊýÄ¿
u16 USART_RX_STA=0;       //½ÓÊÕ״̬±ê¼Ç	  
  
void uart_init(u32 bound){
  //GPIO¶Ë¿ÚÉèÖÃ
  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;	//¸´ÓÃÍÆÍìÊä³ö
  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 ;//ÇÀÕ¼ÓÅÏȼ¶3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//×ÓÓÅÏȼ¶3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQͨµÀʹÄÜ
	NVIC_Init(&NVIC_InitStructure);	//¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯VIC¼Ä´æÆ÷
  
   //USART ³õʼ»¯ÉèÖÃ

	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_ITConfig(USART1, USART_IT_RXNE, ENABLE);//¿ªÆô´®¿Ú½ÓÊÜÖжÏ
  USART_Cmd(USART1, ENABLE);                    //ʹÄÜ´®¿Ú1 

}

void USART1_IRQHandler(void)                	//´®¿Ú1ÖжϷþÎñ³ÌÐò
	{
	u8 Res;
#if SYSTEM_SUPPORT_OS 		//Èç¹ûSYSTEM_SUPPORT_OSΪÕ棬ÔòÐèÒªÖ§³ÖOS.
	OSIntEnter();    
#endif
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //½ÓÊÕÖжÏ(½ÓÊÕµ½µÄÊý¾Ý±ØÐëÊÇ0x0d 0x0a½áβ)
		{
		Res =USART_ReceiveData(USART1);	//¶ÁÈ¡½ÓÊÕµ½µÄÊý¾Ý
		
		if((USART_RX_STA&0x8000)==0)//½ÓÊÕδÍê³É
			{
			if(USART_RX_STA&0x4000)//½ÓÊÕµ½ÁË0x0d
				{
				if(Res!=0x0a)USART_RX_STA=0;//½ÓÊÕ´íÎó,ÖØпªÊ¼
				else USART_RX_STA|=0x8000;	//½ÓÊÕÍê³ÉÁË 
				}
			else //»¹Ã»ÊÕµ½0X0D
				{	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
					{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//½ÓÊÕÊý¾Ý´íÎó,ÖØпªÊ¼½ÓÊÕ	  
					}		 
				}
			}   		 
     } 
#if SYSTEM_SUPPORT_OS 	//Èç¹ûSYSTEM_SUPPORT_OSΪÕ棬ÔòÐèÒªÖ§³ÖOS.
	OSIntExit();  											 
#endif
} 
#endif	




#if EN_USART2_RX   //Èç¹ûʹÄÜÁ˽ÓÊÕ
//´®¿Ú1ÖжϷþÎñ³ÌÐò
//×¢Òâ,¶ÁÈ¡USARTx->SRÄܱÜÃâĪÃûÆäÃîµÄ´íÎó   	
u8 USART2_RX_BUF[USART2_REC_LEN];     //½ÓÊÕ»º³å,×î´óUSART_REC_LEN¸ö×Ö½Ú.
//½ÓÊÕ״̬
//bit15£¬	½ÓÊÕÍê³É±êÖ¾
//bit14£¬	½ÓÊÕµ½0x0d
//bit13~0£¬	½ÓÊÕµ½µÄÓÐЧ×Ö½ÚÊýÄ¿
u16 USART2_RX_STA=0;       //½ÓÊÕ״̬±ê¼Ç	  
  
void uart_init2(u32 bound){
  //GPIO¶Ë¿ÚÉèÖÃ
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//ʹÄÜUSART1£¬GPIOAʱÖÓ 
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
  
	//USART1_TX   GPIOA.9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.9
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//¸´ÓÃÍÆÍìÊä³ö
  GPIO_Init(GPIOA, &GPIO_InitStructure);//³õʼ»¯GPIOA.9
   
  //USART1_RX	  GPIOA.10³õʼ»¯
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//¸¡¿ÕÊäÈë
  GPIO_Init(GPIOA, &GPIO_InitStructure);//³õʼ»¯GPIOA.10  

  //Usart1 NVIC ÅäÖÃ
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//ÇÀÕ¼ÓÅÏȼ¶3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//×ÓÓÅÏȼ¶3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQͨµÀʹÄÜ
	NVIC_Init(&NVIC_InitStructure);	//¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯VIC¼Ä´æÆ÷
  
   //USART ³õʼ»¯ÉèÖÃ

	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(USART2, &USART_InitStructure); //³õʼ»¯´®¿Ú1
  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//¿ªÆô´®¿Ú½ÓÊÜÖжÏ
  USART_Cmd(USART2, ENABLE);                    //ʹÄÜ´®¿Ú1 

}

void USART2_IRQHandler(void)                	//´®¿Ú1ÖжϷþÎñ³ÌÐò
	{
	u8 Res;
#if SYSTEM_SUPPORT_OS 		//Èç¹ûSYSTEM_SUPPORT_OSΪÕ棬ÔòÐèÒªÖ§³ÖOS.
	OSIntEnter();    
#endif
	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //½ÓÊÕÖжÏ(½ÓÊÕµ½µÄÊý¾Ý±ØÐëÊÇ0x0d 0x0a½áβ)
		{
		Res =USART_ReceiveData(USART2);	//¶ÁÈ¡½ÓÊÕµ½µÄÊý¾Ý
		
		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;//½ÓÊÕÊý¾Ý´íÎó,ÖØпªÊ¼½ÓÊÕ	  
					}		 
				}
			}   		 
     } 
#if SYSTEM_SUPPORT_OS 	//Èç¹ûSYSTEM_SUPPORT_OSΪÕ棬ÔòÐèÒªÖ§³ÖOS.
	OSIntExit();  											 
#endif
} 
#endif	



#if EN_USART3_RX   //Èç¹ûʹÄÜÁ˽ÓÊÕ
//´®¿Ú1ÖжϷþÎñ³ÌÐò
//×¢Òâ,¶ÁÈ¡USARTx->SRÄܱÜÃâĪÃûÆäÃîµÄ´íÎó   	
u8 USART3_RX_BUF[USART3_REC_LEN];     //½ÓÊÕ»º³å,×î´óUSART_REC_LEN¸ö×Ö½Ú.
//½ÓÊÕ״̬
//bit15£¬	½ÓÊÕÍê³É±êÖ¾
//bit14£¬	½ÓÊÕµ½0x0d
//bit13~0£¬	½ÓÊÕµ½µÄÓÐЧ×Ö½ÚÊýÄ¿
u16 USART3_RX_STA=0;       //½ÓÊÕ״̬±ê¼Ç	  
  
void uart_init3(u32 bound){
  //GPIO¶Ë¿ÚÉèÖÃ
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//ʹÄÜUSART1£¬GPIOAʱÖÓ 
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
  
	//USART1_TX   GPIOB.10
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA.9
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//¸´ÓÃÍÆÍìÊä³ö
  GPIO_Init(GPIOB, &GPIO_InitStructure);//³õʼ»¯GPIOA.9
   
  //USART1_RX	  GPIOB.11³õʼ»¯
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//¸¡¿ÕÊäÈë
  GPIO_Init(GPIOB, &GPIO_InitStructure);//³õʼ»¯GPIOA.10  

  //Usart1 NVIC ÅäÖÃ
  NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//ÇÀÕ¼ÓÅÏȼ¶3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//×ÓÓÅÏȼ¶3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQͨµÀʹÄÜ
	NVIC_Init(&NVIC_InitStructure);	//¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯VIC¼Ä´æÆ÷
  
   //USART ³õʼ»¯ÉèÖÃ

	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(USART3, &USART_InitStructure); //³õʼ»¯´®¿Ú1
  USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//¿ªÆô´®¿Ú½ÓÊÜÖжÏ
  USART_Cmd(USART3, ENABLE);                    //ʹÄÜ´®¿Ú1 

}

void USART3_IRQHandler(void)                	//´®¿Ú1ÖжϷþÎñ³ÌÐò
	{
	u8 Res;
#if SYSTEM_SUPPORT_OS 		//Èç¹ûSYSTEM_SUPPORT_OSΪÕ棬ÔòÐèÒªÖ§³ÖOS.
	OSIntEnter();    
#endif
	if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  //½ÓÊÕÖжÏ(½ÓÊÕµ½µÄÊý¾Ý±ØÐëÊÇ0x0d 0x0a½áβ)
		{
		Res =USART_ReceiveData(USART3);	//¶ÁÈ¡½ÓÊÕµ½µÄÊý¾Ý
		
		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[USART3_RX_STA&0X3FFF]=Res ;
					USART3_RX_STA++;
					if(USART3_RX_STA>(USART3_REC_LEN-1))USART3_RX_STA=0;//½ÓÊÕÊý¾Ý´íÎó,ÖØпªÊ¼½ÓÊÕ	  
					}		 
				}
			}   		 
     } 
#if SYSTEM_SUPPORT_OS 	//Èç¹ûSYSTEM_SUPPORT_OSΪÕ棬ÔòÐèÒªÖ§³ÖOS.
	OSIntExit();  											 
#endif
} 
#endif	


usart.h文件的内容如下

#ifndef __USART_H
#define __USART_H
#include "stdio.h"	
#include "sys.h" 



#define USART_REC_LEN  			200  	//¶¨Òå×î´ó½ÓÊÕ×Ö½ÚÊý 200
#define EN_USART1_RX 			1		//ʹÄÜ£¨1£©/½ûÖ¹£¨0£©´®¿Ú1½ÓÊÕ
#define USART2_REC_LEN  			200  	//¶¨Òå×î´ó½ÓÊÕ×Ö½ÚÊý 200
#define EN_USART2_RX 			1		//ʹÄÜ£¨1£©/½ûÖ¹£¨0£©´®¿Ú1½ÓÊÕ
#define USART3_REC_LEN 			200  	//¶¨Òå×î´ó½ÓÊÕ×Ö½ÚÊý 200  USART3_REC_LEN
#define EN_USART3_RX 			1		//ʹÄÜ£¨1£©/½ûÖ¹£¨0£©´®¿Ú1½ÓÊÕ


extern u8  USART3_RX_BUF[USART3_REC_LEN]; //½ÓÊÕ»º³å,×î´óUSART_REC_LEN¸ö×Ö½Ú.Ä©×Ö½ÚΪ»»Ðзû 
extern u16 USART3_RX_STA;         		//½ÓÊÕ״̬±ê¼Ç	



	  	
extern u8  USART2_RX_BUF[USART2_REC_LEN]; //½ÓÊÕ»º³å,×î´óUSART_REC_LEN¸ö×Ö½Ú.Ä©×Ö½ÚΪ»»Ðзû 
extern u16 USART2_RX_STA;         		//½ÓÊÕ״̬±ê¼Ç	


extern char  USART_RX_BUF[USART_REC_LEN]; //½ÓÊÕ»º³å,×î´óUSART_REC_LEN¸ö×Ö½Ú.Ä©×Ö½ÚΪ»»Ðзû 
extern u16 USART_RX_STA;         		//½ÓÊÕ״̬±ê¼Ç	
//Èç¹ûÏë´®¿ÚÖжϽÓÊÕ£¬Ç벻ҪעÊÍÒÔϺ궨Òå
void uart_init(u32 bound);
void uart_init2(u32 bound);
void uart_init3(u32 bound);
#endif


5.程序调用

现在串口的函数基本完成,可以在主程序中进行调用,首先我们需要先调用三个串口初始化函数,之后进行发送数据。

//串口波特率均为9600
uart_init(9600);	 
uart_init2(9600);	
uart_init3(9600);	 

此时在main()函数中通过printf()函数已经可以进行字符串的输出,比如

a='1';
printf("a=%c\r\n",a);

此时串口1即可输出

a=1

1.串口接收数据

前面在中断函数中,我们接收一次完成之后,都进行了

USART_RX_STA|=0x8000;

的操作,那么每次接受到一个换行符之后USART_RX_STA的首位都应该是1,那么我们只需要在程序中进行查询该位即可。如果为1 那么一次接受完成,我们可以从 USART_RX_BUF中读出本次接受的数据,同时USART_RX_STA在每接收到一个字符之后都将加一,那么USART_RX_STA中存的就是数据的长度,当然我们需要先将首位数据换回0,而数据长度最多我们设置的200,那么将USART_RX_STA与0x3fff(或者0x7fff  首位为0 且小于200的数据均可以)按位相与即可获得长度。接受函数如0下

if(USART_RX_STA&0x8000){					   
    len=USART_RX_STA&0x3fff;
	printf("Serial1 Receive:\r\n%s\r\n",USART_RX_BUF);
	USART_RX_STA=0;
	for(i=0;i<len;i++) USART_RX_BUF[i]=0;
		}

如果每次就收数据的长度是可变的,那么最后一个for循环是必须的。否则数据将会出错。比如第一次接受12345,第二次如果接收到678的话,如果没有最后一行,那么USART_RX_BUF数组中存的为67845,程序将会出错。

2.串口2和3格式化输出 

 串口2和串口3的输出函数需要自己进行定义,内容如下。

//串口2 发送字符串函数
 void printf2(char* sendData){
	u8 t=0;
	while(sendData[t]!='\0'){
		USART2->DR=sendData[t];
		while((USART2->SR&0X40)==0);//等待发送完完成
		t++;
	}
}
//串口3 发送字符串
 void printf3(char* sendData){
	u8 t=0;
	while(sendData[t]!='\0'){
		USART3->DR=sendData[t];
		while((USART3->SR&0X40)==0);//等待发送完成
		t++;
	}
}

此时main()函数中可以通过调用如下代码完成字符串的输出。

printf2("hello world!\r\n");
printf3("I am AlwaysSun\r\n");

那么如何实现像串口1类似的格式化字符串输出呢?博主一般的做法是采用C语言的sprintf()函数。sprinft()函数的介绍如下

int sprintf( char *buffer, const char *format, [ argument] … );

这个函数包含三个部分的参数:

buffer:char型指针,指向将要写入的字符串的缓冲区。
format:格式化字符串。即可选参数的想要输入的数据类型。

[argument]…:可选参数,可以是任何类型的数据。

简单来说这个函数就是将format格式的字符串,输出到buffer指针指向的地方。这么说有点不好懂,我们用代码举例子

int age=10;
char outString[30]={""};
sprintf(outString,"I am %d years old\r\n",age);

那么字符串outString中保存的内容就是 I am 10 years old\r\n

那么串口2和3实现串口1的功能,方法为

char a='1';
char outString[20]={""};
sprintf(outString,"a=%c\r\n",a);
printf2(outString);

3.串口格式化输入

有时候我们需要获取一个int值,但是串口接受的是字符串类型的数据,如果对字符串进行手动分割之后进行转化,那么将十分的复杂,此时我们可以通过另一个厉害的函数sscanf(),这个函数的用法和sprintf()大致相似,这里不进行介绍。通过串口输入int类型的值例子如下

int getNum=0;
sscanf(USART_RX_BUF,"s-%d-e",&getNum);//UASRT_RX_BUF数组中存放的是串口接收到的数据 s-248-e
printf("getNum=%d\r\n",getNum);

那么将会输出getNum=248。有没有很方便,如果是其他的类型的话,使用方法类似。

4.串口连续输出十六进制数组

有时候我们需要通过十六进制数组成通信协议,如果使用printf这种函数进行发送,那么十分复杂,而采用USART_SendData(USART1,0x01);

搭配for循环这种方法,串口将只能得到最后一个数据,那么如何发送多个十六进制数而不被覆盖呢?我们分析一下,为啥胡数据被覆盖呢,原因只可能是前一个数据还没有发完,或者还是在等待发送的状态,后一个数据就进入到了发送缓冲区,将前一个数据覆盖掉了,那么我们只需要在发送下一个数据的时候,等待前一个数据发送完毕即可。博主一般采用等待发送中断的方法,如下:

void UartA1SendStr(u8 *pucStr,u8 Num) 
{ 
	u8 i; 
	for(i = 0;i<Num;i++) 
	{ 
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); 
			USART_SendData(USART1,*pucStr++); 
	}  
}

这样就可以实现十六进制数组的发送。

本程序整体实现上述功能main()函数代码如下:

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"


char usartReceive2[50]={""};
char usartReceive3[50]={""};
u8 voice_welcome[10]={0x7e,0xff,0x06,0x16,0x00,0x00,0x00,0xfe,0xe5,0xef}; 
int getNum=0;

//´®¿Ú2 ·¢ËÍ×Ö·û´®
 void printf2(char* sendData){
	u8 t=0;
	while(sendData[t]!='\0'){
		USART2->DR=sendData[t];
		while((USART2->SR&0X40)==0);//µÈ´ý·¢ËͽáÊø
		t++;
	}
}
//´®¿Ú3·¢ËÍ×Ö·û´®
 void printf3(char* sendData){
	u8 t=0;
	while(sendData[t]!='\0'){
		USART3->DR=sendData[t];
		while((USART3->SR&0X40)==0);//µÈ´ý·¢ËͽáÊø
		t++;
	}
}

//´®¿Ú1 ·¢ËÍÊ®Áù½øÖÆ×Ö·û´®
void UartA1SendStr(u8 *pucStr,u8 Num) 
{ 
	u8 i; 
	for(i = 0;i<Num;i++) 
	{ 
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); 
			USART_SendData(USART1,*pucStr++); 
	}  
}

//´®¿Ú2 ·¢ËÍÊ®Áù½øÖÆ×Ö·û´®
void UartA2SendStr(u8 *pucStr,u8 Num) 
{ 
	u8 i; 
	for(i = 0;i<Num;i++) 
	{ 
	while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET); 
			USART_SendData(USART2,*pucStr++); 
	}  
}

//´®¿Ú3 ·¢ËÍÊ®Áù½øÖÆ×Ö·û´®
void UartA3SendStr(u8 *pucStr,u8 Num) 
{ 
	u8 i; 
	for(i = 0;i<Num;i++) 
	{ 
	while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET); 
			USART_SendData(USART3,*pucStr++); 
	}  
}


 int main(void)
 {	
	u8 i;
	u8 len,len2,len3;	
	SystemInit();
	delay_init();	    	 //ÑÓʱº¯Êý³õʼ»¯	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// ÉèÖÃÖжÏÓÅÏȼ¶·Ö×é2
	uart_init(9600);	 //´®¿Ú³õʼ»¯Îª9600
	 uart_init2(9600);	 //´®¿Ú³õʼ»¯Îª9600
	 uart_init3(9600);	 //´®¿Ú³õʼ»¯Îª9600
	LED_Init();		  	 //³õʼ»¯ÓëLEDÁ¬½ÓµÄÓ²¼þ½Ó¿Ú 
 
	while(1)
	{
		LED0=!LED0;
		//´®¿Ú·¢ËÍ×Ö·û´®
		printf("Hello Everyone.I Am Serial1\r\n");
		printf2("Hello Everyone.I Am Serial2\r\n");
		printf3("Hello Everyone.I Am Serial3\r\n");
		
		//´®¿Ú·¢ËÍÊ®Áù½øÖÆ×Ö·ûÊý×é
		/*UartA1SendStr(voice_welcome,10);
		UartA2SendStr(voice_welcome,10);
		UartA3SendStr(voice_welcome,10);*/
		if(USART_RX_STA&0x8000)
		{					   
			len=USART_RX_STA&0x3fff;//µÃµ½´Ë´Î½ÓÊÕµ½µÄÊý¾Ý³¤¶È  0011
			printf("Serial1 Receive:\r\n%s\r\n",USART_RX_BUF);
			sscanf(USART_RX_BUF,"s-%d-e",&getNum);
			printf("getNum=%d\r\n",getNum);
			USART_RX_STA=0;
			for(i=0;i<len;i++) USART_RX_BUF[i]=0;
		}
		
		if(USART2_RX_STA&0x8000)
		{					   
			len2=USART2_RX_STA&0x3fff;//µÃµ½´Ë´Î½ÓÊÕµ½µÄÊý¾Ý³¤¶È
			sprintf(usartReceive2,"Serial2 Receive:\r\n%s\r\n",USART2_RX_BUF);//USART2_RX_BUF
			printf2(usartReceive2);
			USART2_RX_STA=0;
			for(i=0;i<len2;i++) USART2_RX_BUF[i]=0;
		}
		
		if(USART3_RX_STA&0x8000)
		{					   
			len3=USART3_RX_STA&0x3fff;//µÃµ½´Ë´Î½ÓÊÕµ½µÄÊý¾Ý³¤¶È
			sprintf(usartReceive3,"Serial3 Receive:\r\n%s\r\n",USART3_RX_BUF);
			printf3(usartReceive3);
			USART3_RX_STA=0;
			for(i=0;i<len3;i++) USART3_RX_BUF[i]=0;
		}
		delay_ms(1500);
	}	 
}


项目下载地址https://download.csdn.net/download/qq_34020487/11962625

已标记关键词 清除标记
相关推荐
如题,最近做一个这样的调试,用32的开发板向电脑发送数据,用普通的串口调试助手就可以正常收发。 实际如下:32设备收到发来的信号,然后再将另外一组数据发送到调试助手 ![图片说明](https://img-ask.csdn.net/upload/201810/23/1540282792_7501.png) 然后在普通的串口调试助手上就是这样的; 我自己根据博客上的代码写了个差不多的串口工具,用的是Communications control ,version6.0这个控件写的。 但是结果上来说,如果32定时自己向这个工具发数据的话是可以发的,工具也能收到并且显示出来,但是用这个工具向32发数据32却收不到。 因此我又用了虚拟串口,用电脑上的串口调试助手和我写的工具互相收发,双方也都是能收到数据,也能互相发送数据,请大神帮我看看到底是那里出了问题! 串口工具收到32的数据: ![图片说明](https://img-ask.csdn.net/upload/201810/23/1540283320_110440.png) 但是这个串口工具向32发送时32却收不到数据。 为了验证串口可以发送,我用了虚拟串口,如下: ![图片说明](https://img-ask.csdn.net/upload/201810/23/1540283543_713052.png) STM32的程序如下: void UART1_Send_Array() // { unsigned char i=0; // unsigned char t=0; // num=8; for(i=0;i<num;i++) { USART_SendData(USART1,send_array[t]); // while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);// t++; } } if(USART_RX_STA&0x8000) { UART1_Send_Array(); USART_RX_STA=0; LED0=!LED0; } 以及初始化等 #if EN_USART1_RX //Èç¹ûʹÄÜÁ˽ÓÊÕ //´®¿Ú1ÖжϷþÎñ³ÌÐò //×¢Òâ,¶ÁÈ¡USARTx->SRÄܱÜÃâĪÃûÆäÃîµÄ´íÎó u8 USART_RX_BUF[USART_REC_LEN]; //½ÓÊÕ»º³å,×î´óUSART_REC_LEN¸ö×Ö½Ú. //½ÓÊÕ״̬ //bit15£¬ ½ÓÊÕÍê³É±êÖ¾ //bit14£¬ ½ÓÊÕµ½0x0d //bit13~0£¬ ½ÓÊÕµ½µÄÓÐЧ×Ö½ÚÊýÄ¿ u16 USART_RX_STA=0; //½ÓÊÕ״̬±ê¼Ç void uart_init(u32 bound){ //GPIO¶Ë¿ÚÉèÖà 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; //¸´ÓÃÍÆÍìÊä³ö 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 ;//ÇÀÕ¼ÓÅÏȼ¶3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //×ÓÓÅÏȼ¶3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQͨµÀʹÄÜ NVIC_Init(&NVIC_InitStructure); //¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯VIC¼Ä´æÆ÷ //USART ³õʼ»¯ÉèÖà 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_ITConfig(USART1, USART_IT_RXNE, ENABLE);//¿ªÆô´®¿Ú½ÓÊÜÖÐ¶Ï USART_Cmd(USART1, ENABLE); //ʹÄÜ´®¿Ú1 } void USART1_IRQHandler(void) //´®¿Ú1ÖжϷþÎñ³ÌÐò { u8 Res; #if SYSTEM_SUPPORT_OS //Èç¹ûSYSTEM_SUPPORT_OSΪÕ棬ÔòÐèÒªÖ§³ÖOS. OSIntEnter(); #endif if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //½ÓÊÕÖжÏ(½ÓÊÕµ½µÄÊý¾Ý±ØÐëÊÇ0x0d 0x0a½áβ) { Res =USART_ReceiveData(USART1); //¶ÁÈ¡½ÓÊÕµ½µÄÊý¾Ý if((USART_RX_STA&0x8000)==0)//½ÓÊÕδÍê³É { if(USART_RX_STA&0x4000)//½ÓÊÕµ½ÁË0x0d { if(Res!=0x0a)USART_RX_STA=0;//½ÓÊÕ´íÎó,ÖØпªÊ¼ else USART_RX_STA|=0x8000; //½ÓÊÕÍê³ÉÁË } else //»¹Ã»ÊÕµ½0X0D { if(Res==0x0d)USART_RX_STA|=0x4000; else { USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; USART_RX_STA++; if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//½ÓÊÕÊý¾Ý´íÎó,ÖØпªÊ¼½ÓÊÕ } } } } #if SYSTEM_SUPPORT_OS //Èç¹ûSYSTEM_SUPPORT_OSΪÕ棬ÔòÐèÒªÖ§³ÖOS. OSIntExit(); #endif } #endif 主要就是设置GPIO口,设置波特率等等 VS2010的主要程序如下: void CSerialTestDlg::OnCbnSelchangeComboCom() { // TODO: 在此添加控件通知处理程序代码 int nSel; nSel = m_comboCom.GetCurSel();//获取组合框控件的列表框中选中项的索引 m_ctrlComm.put_CommPort(nSel+1);//选择串口号(这里因为列表框的索引号是从0开始,所以(nSel+1)对应的才是我们所选的串口号) m_ctrlComm.put_PortOpen(TRUE);//打开串口 m_ctrlComm.put_RThreshold(2);//收到两个字节引发OnComm事件 m_ctrlComm.put_InputMode(1);//输入模式选为二进制 m_ctrlComm.put_Settings(_T("9600,n,8,1"));//设置串口参数,波特率,无奇偶校验,位停止位,位数据位 m_ctrlComm.put_InputMode(1); // 以二进制方式检取数据 m_ctrlComm.put_RThreshold(1); //参数1表示每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的OnComm事件 m_ctrlComm.put_InputLen(0); //设置当前接收区数据长度为0 m_ctrlComm.get_Input();//先预读缓冲区以清除残留数据 m_setOk = true; //标记串口设置OK } BEGIN_EVENTSINK_MAP(CSerialTestDlg, CDialogEx) ON_EVENT(CSerialTestDlg, IDC_MSCOMM1, 1, CSerialTestDlg::OnComm, VTS_NONE) END_EVENTSINK_MAP() void CSerialTestDlg::OnComm() { // TODO: 在此处添加消息处理程序代码 VARIANT variant_inp; //Variant 是一种特殊的数据类型,除了定长String数据及用户定义类型外,可以包含任何种类的数据。 COleSafeArray safearray_inp; LONG len,k; BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integer that is not signed. CString strtemp; if(m_ctrlComm.get_CommEvent() == 2) //事件值为2表示接收缓冲区内有字符 { ////////以下你可以根据自己的通信协议加入处理代码 variant_inp=m_ctrlComm.get_Input(); //读缓冲区 safearray_inp=variant_inp; //VARIANT型变量转换为ColeSafeArray型变量 len=safearray_inp.GetOneDimSize(); //得到有效数据长度 for(k=0;k<len;k++) safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组 for(k=0;k<len;k++) //将数组转换为Cstring型变量 { BYTE bt=*(char*)(rxdata+k);//字符型 strtemp.Format(_T("%x"),bt); //8位数组显示,就是现在strtemp中是51 00 00 00 0 m_strRXData+=strtemp; //加入接收编辑框对应字符串 } } UpdateData(FALSE); //更新编辑框内容 } void CSerialTestDlg::OnBnClickedButtonSend() { // TODO: 在此添加控件通知处理程序代码 if (m_setOk == true) //判断是否打开并初始化串口 { UpdateData(TRUE); //读取编辑框内容 m_ctrlComm.put_Output(COleVariant(m_strTXData)); //发送数据 } else { MessageBox(_T("请先选择COM口")); } } void CSerialTestDlg::OnBnClickedButtonCleanup() { // TODO: 在此添加控件通知处理程序代码 m_strRXData=""; UpdateData(FALSE);//更新编辑框内容 } 请求大神帮我看一下大概是哪里出现了问题!
课程简介: 历经半个多月的时间,Debug亲自撸的 “企业员工角色权限管理平台” 终于完成了。正如字面意思,本课程讲解的是一个真正意义上的、企业级的项目实战,主要介绍了企业级应用系统中后端应用权限的管理,其中主要涵盖了六大核心业务模块、十几张数据库表。 其中的核心业务模块主要包括用户模块、部门模块、岗位模块、角色模块、菜单模块和系统日志模块;与此同时,Debug还亲自撸了额外的附属模块,包括字典管理模块、商品分类模块以及考勤管理模块等等,主要是为了更好地巩固相应的技术栈以及企业应用系统业务模块的开发流程! 核心技术栈列表: 值得介绍的是,本课程在技术栈层面涵盖了前端和后端的大部分常用技术,包括Spring Boot、Spring MVC、Mybatis、Mybatis-Plus、Shiro(身份认证与资源授权跟会话等等)、Spring AOP、防止XSS攻击、防止SQL注入攻击、过滤器Filter、验证码Kaptcha、热部署插件Devtools、POI、Vue、LayUI、ElementUI、JQuery、HTML、Bootstrap、Freemarker、一键打包部署运行工具Wagon等等,如下图所示: 课程内容与收益: 总的来说,本课程是一门具有很强实践性质的“项目实战”课程,即“企业应用员工角色权限管理平台”,主要介绍了当前企业级应用系统中员工、部门、岗位、角色、权限、菜单以及其他实体模块的管理;其中,还重点讲解了如何基于Shiro的资源授权实现员工-角色-操作权限、员工-角色-数据权限的管理;在课程的最后,还介绍了如何实现一键打包上传部署运行项目等等。如下图所示为本权限管理平台的数据库设计图: 以下为项目整体的运行效果截图: 值得一提的是,在本课程中,Debug也向各位小伙伴介绍了如何在企业级应用系统业务模块的开发中,前端到后端再到数据库,最后再到服务器的上线部署运行等流程,如下图所示:
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页