单片机UART的收发设计

本文介绍STM32F0系列单片机通过USART实现串行通信的方法,重点讲解利用定时器中断实现数据接收超时的配置流程。包括配置时钟源、初始化GPIO、USART及定时器,以及如何通过NVIC进行中断管理。
摘要由CSDN通过智能技术生成

简介

UART传输是我们实际应用开发中最常用的一种串行通信方式。关于通信方式有许多种类:串行,并行,单工,半双工,全双工,异步,同步等等。波特率是衡量通信速度的单位。比如2400bps = (1个停止位+1个结束位+8位数据位)* 240,也就是一秒钟传输240个字节。
在单片机中,当每次来数据的时候,都会产生中断,这个中断函数调用的地方是在启动文件(.s)中调用的,函数名也是固定的,所以我们只需要重构这个相应的中断函数就可以了。
但是实际应用中我们会有个问题,就是我们一般都是等传输结束后再去处理数据(对于一般有数据格式的还好,自行判断),但是什么时候结束尼,这是个问题。
实际有两个方法:

  1. 利用DMA的空闲中断
  2. 使用定时器做超时中断(比如说10ms没数据就等于传输结束)
    下面主要介绍下利用定时器做超时中断

配置流程

本例程以stm32F0为例:

配置时钟源

/*这里的USART2是挂在APB1时钟线上,RCC模块提供了许多关于时钟相关的配置*/
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);  //使能GPIOA的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE); //使能TIM14的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);//使能USART的时钟

初始化

GPIO初始化

  GPIO_InitTypeDef GPIO_InitStructure;
  /*USART相应管脚初始化 USART2_TX ->PA2*/  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;	       //选中串口默认输出管脚
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;  //定义GPIO功能,这里是复用功能,可以使用
  /*GPIO_PinAFConfig函数注册管脚的复用功能*/
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /*定义管脚的模式为推挽输出,实际用不上推挽方式,可以保证驱动能力*/
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;/*上拉*/
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//GPIO的频率
  GPIO_Init(GPIOA, &GPIO_InitStructure); //GPIO初始化

  /*如果需要配置RX就配置一下RX相应的管脚,管脚模式要改为输入或者浮空*/

USART初始化

  USART_InitTypeDef USART_InitStructure;  //定义串口初始化结构体
 /*串口通讯参数设置*/
  USART_InitStructure.USART_BaudRate = 9600; //波特率
  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;
  /*硬件流控制,需要相应的CTX和RTX配和*/
  USART_InitStructure.USART_Mode = USART_Mode_Tx;		//配置USART的模式,TX还是RX
  USART_Init(USART_DEBUG, &USART_InitStructure); /*初始化USART*/
  USART_ITConfig(USART, USART_IT_RXNE, ENABLE); /*使能接收完完成中断*/

定时器初始化

TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = (ms-1);/*装载值(其实这里比较好理解,我们配置好时钟后,
就可以知道1s产生多少次计数,这里就是计数值)--(该装载值/1s产生的总计数)s,计算出来的就是多少
秒产生中断*/
TIM_TimeBaseStructure.TIM_Prescaler =(div-1);/*预分频值,+1为分频系数
TIM_CLK = APB1_CLK / (div+1)  
比如说主频是48M,div我们设置为4799,
那TIM的频率就是1M,即1秒产生(48,000,000 / 4800 = 10,000)个计数*/
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //还不清楚具体干嘛,一般都填0
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;	/*TIM向上计数模式,累加的,
比如说装载值为1999,即计数到1999的时候产生中断,前提是打开了中断*/
TIM_TimeBaseInit(tim, &TIM_TimeBaseStructure); /*根据TIM_TimeBaseInitStruct中指定的
参数初始化TIMx的时间基数单位*/
TIM_ITConfig(tim,TIM_IT_Update,ENABLE);	//使能TIM中断源

中断初始化

/*中断管理模块是在NVIC模块下,可以配置*/
NVIC_InitTypeDef         NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = channle;//中断通道,中断源里面有相应的宏,比如:TIM14_IRQn
NVIC_InitStructure.NVIC_IRQChannelPriority = priority; //中断优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道被使能
NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

使能

TIM_Cmd(tim, ENABLE);  	//使能TIMx外设		
USART_Cmd(USART_DEBUG, ENABLE); //使能USART

收发

void USART1_IRQHandler(void)
{
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
	{
        if(rcv_flag == 0){  /*是否刚开始接收*/
            timer_cmd(AT_TIMER,1); /*开启定时器*/
            timer_set_count(AT_TIMER,0); /*清空计数*/
        } 
        rcv_flag = 1;  /*已经在接收过程中了*/
        if(rcv_offset >= MAX_RECV_NUM){  /*大于最大接收数,防止数组越界*/
            USART_ReceiveData(USART1); /*用做清中断*/  
            return;
        }
        rcv_buf[rcv_offset] = (uint8_t)USART_ReceiveData(USART1);  /*接收数据并保存到数组中*/
        rcv_offset++;  /*数据偏移1个字节*/
        timer_set_count(AT_TIMER,0); /*重置定时器*/
	}
}

/*该定时器用于串口接收超时判断*/
void TIM14_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM14, TIM_IT_Update) != RESET) //定时器中断
	{
        rcv_end = 1;
        timer_cmd(AT_TIMER,0); //关闭定时器
		TIM_ClearITPendingBit(TIM14, TIM_FLAG_Update); //清除中断待处理位
	}
}


寄存器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值