stm32f10x串口通信的写法

目录

一、串口配置

1.1、数据类型重新定义及调试用的宏

1.2、端口封装 

1.3、串口通信逻辑代码

1.4、中断服务函数

1.5、支持printf

1.6、中断及串口的封装


一、串口配置

1.1、数据类型重新定义及调试用的宏

/***********************无符号类型的定义****************************/
typedef unsigned char st_u8;
typedef unsigned short int st_u16;
typedef unsigned int st_u32;


//typedef unsigned __INT64 st_u64;
/***********************有符号类型的定义****************************/
typedef signed char st_8;
typedef signed short int st_16;
typedef signed int st_32;

/***********************其他数据类型定义方式****************************/
#define uint8    unsigned char
#define uint16   unsigned short int
#define uint32   unsigned long int
#define int8     signed char
#define int16    signed short int
#define int32    signed long int
#define uint64   unsigned long long int
#define int64    signed long long int

//typedef signed __INT64 st_64
/*********************************************全局变量条件编译***************************************/
#ifdef ROOT
#define EXT
#define ext
#else
#define EXT extern
#define ext extern
#endif


/*********************************************位定义*********************************************/
typedef enum
{
	FALSE = 0,
	TRUE = !FALSE
}boot;

/*********************************************调试宏*****************************************/ 
#define DEBUG_USART_PRINTF 1   //  printf 使能

#define USART1_ENABLE 1
#define USART2_ENABLE 1
#define USART3_ENABLE 1

1.2、端口封装 

//  GPIO时钟 宏定义
#define GPIOx_RCC_APB2Periph RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC \
                             RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOF \
														 RCC_APB2Periph_GPIOG


void GPIOx_config(st_u32 GPIOx_RCC,GPIO_TypeDef *GPIOxPORT,st_u16 GPIOPin,GPIOMode_TypeDef GPIOMode)
{
   RCC_APB2PeriphClockCmd(GPIOx_RCC, ENABLE);
  GPIO_InitTypeDef GPIO_InitStructure;
  /* Configure PD0 and PD2 in output pushpull mode */
  GPIO_InitStructure.GPIO_Pin =GPIOPin;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIOMode;
  GPIO_Init(GPIOxPORT, &GPIO_InitStructure);
}



st_u8 GPIOSet(GPIO_TypeDef* GPIOx, uint16_t GPIOPin, uint16_t GPIOMode)
{
	if(GPIOMode == 0)
	{
		//USART3->DR
		GPIO_ResetBits(GPIOx,GPIOPin);
	}
	else
	{
		GPIO_SetBits(GPIOx,GPIOPin);
	}
	return GPIOMode;
}

//  uint8_t GPIOGet(GPIO_TypeDef* GPIOx, uint16_t GPIOPin)
st_u8 GPIOGet(GPIO_TypeDef* GPIOx, uint16_t GPIOPin)
{
	return (GPIO_ReadInputDataBit(GPIOx, GPIOPin));
}

1.3、串口通信逻辑代码

static void Uart1_Config(void);
/*********************************************USART1*****************************************/

#if USART1_RX_EN

void Uart1_Config(void) {
    NVIC_Config(USART1_IRQn, 2, 1);
    GPIOx_config(GPIOx_CLK, USART1_PORT, USART1_TX_PIN, GPIO_Mode_AF_PP); //  TX  PA9 复用推挽输出
    GPIOx_config(GPIOx_CLK, USART1_PORT, USART1_RX_PIN, GPIO_Mode_IN_FLOATING); // RX  PA10 浮空输入
    USART_Config(115200, USART1);
}


void UART1Init(void) {
    USART_RX_STA = 0;
    Uart1_Config();
}		
		
		
void USART1_Int(void){
    //	INTX_DISABLE();
    st_u8 r; //temp;
    //  是否发生接收中断  1发生  0 没有发生
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
    {
        r = USART_ReceiveData(USART1); //(USART1->DR);	//读取接收到的数据
        if ((USART_RX_STA & 0x8000) == 0) //接收未完成
        {
            if (USART_RX_STA & 0x4000) //接收到了0x0d
            {
                if (r != 0x0a) USART_RX_STA = 0; //接收错误,重新开始
                else USART_RX_STA |= 0x8000; //接收完成了 
            } else //还没收到0X0D
            {
                if (r == 0x0d) USART_RX_STA |= 0x4000;
                else {
                    USART_RX_BUF[USART_RX_STA & 0X3FFF] = r;
                    USART_RX_STA++;
                    if (USART_RX_STA > (USART_REC_LEN - 1)) USART_RX_STA = 0; //接收数据错误,重新开始接收	  
                }
            }
        }
    }
}
#endif
/*********************************************测试PRINTF*********************************************/
/*********************************************USART2*****************************************/
void UART1_Test(void) 
{
 printf("提示信息:%s\r\n", "USART1测试");
}
#ifndef _USART_H
#define _USART_H
/*********************************************USART1*****************************************/
#define USART1_RCC   RCC_APB2Periph_USART1    //  串口时钟
#define USART1_PORT  GPIOA                    //  端口

#define GPIOx_CLK      RCC_APB2Periph_GPIOA   //  端口时钟
#define USART1_TX_PIN  GPIO_Pin_9             //  USART1_TX
#define USART1_RX_PIN  GPIO_Pin_10            //  USART1_RX

#define USART1_RX_EN 1                        //  uSART1使能位
#define USART_REC_LEN 200                     //  接受数组

#define USART_SEC_LEN 200                     //  发送数组

//  bit0~13 接收有效数据的长度
//  bit14   接收0xOD  回车的表示由 2 个字节组成:0X0D 和 0X0A
//  bit15   接收完成的标记
ext st_u16 USART_RX_STA;
ext st_u8 USART_RX_BUF[USART_REC_LEN];

extern  void UART1Init(void);
extern  void UART1_Test(void);
extern  void USART1_Int(void);

/*********************************************USART2*****************************************/
#endif

1.4、中断服务函数

写在stm32f10x_it.c文件中

void USART1_IRQHandler(void)
{
    USART1_Int();
}

1.5、支持printf

/*********************************************串口printf函数的使用*********************************************/
#if DEBUG_USART_PRINTF
#pragma import (__use_no_semihosting)  //  确保没有从 C 库链接使用半主机的函数

//  标准库需要的支持函数                 
struct __FILE {int handle;};

FILE __stdout;

void _sys_exit(int x) { x = x;}        // 定义 _sys_exit() 以避免使用半主机模式

 
 // 重定义fputc函数 
int fputc(int ch, FILE * f) {
    #if 0
    while ((USART1 - > SR & 0X40) == 0) //  循环发送,直到发送完毕   
        USART1 - > DR = (u8) ch;
    return ch;
   #else
	      if(USART2_ENABLE==1){
        USART_SendData(USART2, (st_u8) ch);
				//while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET){}
        while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);   // USART_FLAG_TXE  数据寄存器为空的标记
				}else if(USART1_ENABLE==1){
			 USART_SendData(USART1, (st_u8) ch);
       while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);   // USART_FLAG_TXE  数据寄存器为空的标记
				}else if(USART3_ENABLE==1){
			  USART_SendData(USART3, (st_u8) ch);
       while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);   // USART_FLAG_TXE  数据寄存器为空的标记
				}
        return ch;
    #endif
}

//  接收数据
//  重定向 c 库函数 scanf 到串口,重写向后可使用 scanf、getchar 等函数
int fgetc(FILE * f) {
	  static st_u32 TempData;
	  if(USART2_ENABLE==1){
    while(USART_GetFlagStatus(USART2, USART_IT_RXNE) == RESET)
			TempData=USART_ReceiveData(USART2);
   // return (st_32) USART_ReceiveData(USART2);
		}else if(USART1_ENABLE==1){
		while (USART_GetFlagStatus(USART1, USART_IT_RXNE) == RESET)
    TempData= USART_ReceiveData(USART1);
		}else if(USART3_ENABLE==1){
		while (USART_GetFlagStatus(USART3, USART_IT_RXNE) == RESET)
    TempData= USART_ReceiveData(USART3);
		}
		return TempData;
}




/*********************************************向串口发送一个字符/字节*********************************************/
void Usart_SendByte(USART_TypeDef * pUSARTx, st_u8 ch) {
	
    USART_SendData(pUSARTx, ch);
    while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}




/*********************************************向串口发送字符串*********************************************/
void Usart_SendString(USART_TypeDef * pUSARTx, char * str) {
    st_u32 k = 0;
    do {
        Usart_SendByte(pUSARTx, * (str + k));
        k++;
    } while ( * (str + k) != '\0');
    while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET); // 等待发送完成  
}
#endif




/*********************************************获取一个数据的字节长度(最大255)*********************************************/
st_u8 ByteLen(st_u8 *p)  // 字符长度
{
	st_u8 Count = 0;
	//  获取Bye数目,#define  SEC_BYTESIZE_MAX 200 
	for(st_u8 i=0;i<200;i++)
	{
		//  指针指向'0'地址结束结束计数
		if((*(p+i))!= '\0'){
		Count++;
		}else{
			break;
		}
	}
	return Count;
}



/*********************************************获取一个数据的字节长度(16位,最大65535)*********************************************/
st_u8 ByteLen_16(st_u16 *p)  // 字符长度
{
	st_u8 Count = 0;
	//  获取Bye数目,#define  SEC_BYTESIZE_MAX 200 
	for(st_u8 i=0;i<200;i++)
	{
		//  指针指向'0'地址结束结束计数
		if((*(p+i))!= '\0'){
		Count++;
		}else{
			break;
		}
	}
	return Count;
}



/*********************************************获取一个数据的字节长度(32位)*********************************************/
st_u8 ByteLen_32(st_u32 *p)  // 字符长度
{
	
	st_u8 Count = 0;
	//  获取Bye数目,#define  SEC_BYTESIZE_MAX 200 
	for(st_u8 i=0;i<200;i++)
	{
		//  指针指向'0'地址结束结束计数
		if((*(p+i))!= '\0'){
		Count++;
		}else{
			break;
		}
	}
	return Count;
}



/*********************************************将指定个数的字符串从一个地方拷贝到另外一个地方*********************************************/
st_u8 *rt_strncpy(st_u8 *dst, const st_u8 *src, st_u32 n)
{
    if (n != 0)
    {
        st_u8 *d = dst;
        const st_u8 *s = src;

        do
        {
            if ((*d++ = *s++) == 0)
            {
                /* NUL pad the remaining n-1 bytes */
                while (--n != 0)
                    *d++ = 0;
                break;
            }
        } while (--n != 0);
    }

    return (dst);
}

1.6、中断及串口的封装

/********************************************* 中断优先级配置*********************************************/
//  中断分组配置  NVIC_PriorityGroupConfig
void NVIC_PG_Config(st_u32 PG)
{
/*
	中断分组号      抢占式优先级    子优先级配置/响应式优先级     分配位数
	0               0                  0-15                      抢0bit  响4bit(1111)
	1               0~1                0~7                       抢1bit  响3bit(0111) 
	2               0~3                0~3                       抢2bit  响2bit(0011)
	3               0~7                0~1                       抢3bit  响1bit(0001)
	4               0~15               0                         抢4bit  响0bit(0000)
  特征:在抢占式优先级相同的情况下,高响应优先级的中断优先被响应。
        抢占式优先级数值越小,优先级越高
	*/
  if(PG==NVIC_PriorityGroup_0)
	{
	   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
	}else if(PG==NVIC_PriorityGroup_1){	
		 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	}else if(PG==NVIC_PriorityGroup_2) {
		 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	}	else if(PG==NVIC_PriorityGroup_3){ 
	  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
	}else if(PG==NVIC_PriorityGroup_4){    
	  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
	}else{
	    printf("%s","没有使用中断分组\r\n");
	}
}
//  中断优先级配置
void NVIC_Config(st_u8 IRQn,st_u8 IRQChannelPriority,st_u8 IRQChannelSubPriority)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  NVIC_InitStructure.NVIC_IRQChannel = IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =IRQChannelPriority;   //  抢占式优先级 0~15
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =IRQChannelSubPriority ;      //  子优先级 0~15
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

//  外部中断配置
void EXTI_Config(void){
	                            // 外部中断初始化
}
/*********************************************串口配置*********************************************/
void USART_Config(st_u32 BaudRate,USART_TypeDef* USARTx)
{
	USART_InitTypeDef USART_InitStructure;
	if(USARTx==USART1)RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	if(USARTx==USART2)RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
	/* USART1工作模式配置 */
	USART_InitStructure.USART_BaudRate = BaudRate;	//波特率设置:
	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(USARTx, &USART_InitStructure);  //初始化USART1
	// 使能串口接收中断
	USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE);	
	//  使能中断发送
	USART_ITConfig(USARTx, USART_IT_TXE, ENABLE);
	USART_Cmd(USARTx, ENABLE);       // USART使能
}

猜你喜欢

转载自blog.csdn.net/RONG_YAO/article/details/128005016