3.合宙Air32F103_USART_TIMER

一、简介

本章目的:在上一章已实现串口的基础上,添加定时器的功能。实现串口接收帧的时间间隔标志,当超过10ms没收到串口数据时处理当前已接收到的数据。

二、从例程移植

由于已经实现了串口的例程,只需要找到定时器的相关例程即可。

找到定时器工程的例程:

ModuleDemo\TIM\TIM_Basic\USER\TIM.uvprojx

3.合宙Air32F103_USART_TIMER_第1张图片

3.合宙Air32F103_USART_TIMER_第2张图片

三、移植

具体的移植过程,不再介绍了,将初始化和中断配置的部分复制过来就可以了。

3.1timer.c

在timer.c中包括定时器2和3初始化,使用串口3和串口配合实现时间间隔帧标志判断,串口2定时5秒定时发送欢迎语句。

#include

#include "timer.h"

#include "delay.h"

#include "usart.h"

void TIM2_Int_Init(u16 arr,u16 psc)

{

       TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

       NVIC_InitTypeDef NVIC_InitStructure;

       RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能

      

       //定时器TIM3初始化

       TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值      

       TIM_TimeBaseStructure.TIM_Prescaler = psc; //设置用来作为TIMx时钟频率除数的预分频值

       TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim

       TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式

       TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位

       TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断

       //中断优先级NVIC设置

       NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //TIM2中断

       NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级

       NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;  //从优先级3级

       NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能

       NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器

       TIM_Cmd(TIM2, ENABLE);  //使能TIMx

//     TIM_Cmd(TIM2, DISABLE);  //使能TIMx   

}

//通用定时器3中断初始化

//这里时钟选择为APB1的2倍,而APB1为36M

//arr:自动重装值。

//psc:时钟预分频数

//这里使用的是定时器3!

void TIM3_Int_Init(u16 arr,u16 psc)

{

  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

       NVIC_InitTypeDef NVIC_InitStructure;

       RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

      

       //定时器TIM3初始化

       TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值      

       TIM_TimeBaseStructure.TIM_Prescaler = psc; //设置用来作为TIMx时钟频率除数的预分频值

       TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim

       TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式

       TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位

       TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断

       //中断优先级NVIC设置

       NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断

       NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级

       NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级

       NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能

       NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器

//     TIM_Cmd(TIM3, ENABLE);  //使能TIMx

       TIM_Cmd(TIM3, DISABLE);  //使能TIMx

}

//定时器2中断服务程序

void TIM2_IRQHandler(void)   //TIM2中断

{

       u8 st;

       st= TIM_GetFlagStatus(TIM2, TIM_FLAG_Update);    

       if(st==SET)

       {

              TIM_ClearFlag(TIM2, TIM_FLAG_Update);

              printf("wuzjjj,07-11\r\n");

       }

}

//定时器3中断服务程序

void TIM3_IRQHandler(void)   //TIM3中断

{

       u8 st;

       st= TIM_GetFlagStatus(TIM3, TIM_FLAG_Update);    

       if(st==SET)

       {

              TIM_ClearFlag(TIM3, TIM_FLAG_Update);

              //printf("wuzjjj\r\n");

              USART1_RX_STA|=1<<15;  //标记接收完成 

              TIM_Cmd(TIM3, DISABLE);  //关闭TIM3

       }

}

3.2usart.h

#ifndef __TIMER_H__

#define __TIMER_H__

#include "sys.h"

void TIM2_Int_Init(u16 arr,u16 psc);

void TIM3_Int_Init(u16 arr,u16 psc);

#endif

3.3usart.c

usart.c中添加相关处理。每次接收到数据后,将定时器清零,将数据存到数组USART1_RX_BUF。第一次接收数据,需要使能定时器中断。

void USART1_IRQHandler(void)                     //串口1中断服务程序

{

       u8 st,sbuf;

       st=USART_GetITStatus(USART1, USART_IT_RXNE);

       if(st==SET)  //

       {

              sbuf=USART1->DR;

//     usart1_1_byte(sbuf);

              if((USART1_RX_STA&(1<<15))==0)//接收完的一批数据,还没有被处理,则不再接收其他数据

              {

                     if(USART1_RX_STA

                     {

                            TIM_SetCounter(TIM3,0);//计数器清空                                    //计数器清空

                            if(USART1_RX_STA==0)                          //使能定时器7的中断

                            {

                                   TIM_Cmd(TIM3,ENABLE);//使能定时器7

                            }

                            USART1_RX_BUF[USART1_RX_STA++]=sbuf;  //记录接收到的值     

                     }else

                     {

                            USART1_RX_STA|=1<<15;                       //强制标记接收完成

                     }

              }

       }

}

3.4main.c

main.c中包括初始化等操作。将官方例程中的CLK打印封装到CLK_Printf中。

#include

#include

#include

#include "delay.h"

#include "led.h"

#include "usart.h"

#include "timer.h"

void CLK_Printf(void);

int main(void)

{

       int t=0;

       delay_init();                                                                        //延时初始化

       uart1_init(115200);                                                      //串口1初始化

       TIM3_Int_Init(10000-1,72-1);               //定时器3初始化,10ms

       TIM2_Int_Init(10000-1,36000-1);         //定时器2初始化,5000ms

       clear_usart1_buffer();                                           //清空串口1接受buffer

      

       CLK_Printf();                                                                            //打印时钟频率

      

       LED_GPIO_Init();                                                             //LED闪烁

      

       printf("wuzjjj\r\n");                                               //打印欢迎语句

       while (1)

       {

              if(USART1_RX_STA&0x8000)                         //收到串口数据

              {

                     USART1_RX_STA = USART1_RX_STA&0x7FFF;             //去掉标志位,剩下数据长度

                     printf("received,%d:",USART1_RX_STA);        //发送辅助信息及收到的数据长度

                     printf("%s\r\n",USART1_RX_BUF);                                //将收到的数据发回

                     clear_usart1_buffer();                                                                //清空串口1接受buffer

              }

             

              if(t%200)                                                                                   //200ms执行一次LED控制

              {

                     LED_Set(t/200);                                                   //LED控制命令

              }

              t++;                                                                                            //时间+1

              delay_ms(1);                                                                       //延时1ms

       }

}

void CLK_Printf(void)

{

       RCC_ClocksTypeDef clocks;

       RCC_GetClocksFreq(&clocks); //获取系统时钟频率

       printf("SYSCLK:%.1fMhz,HCLK:%.1fMhz,PCLK1:%.1fMhz,PCLK2:%.1fMhz,ADCCLK:%.1fMhz\r\n",

              (float)clocks.SYSCLK_Frequency/1000000,(float)clocks.HCLK_Frequency/1000000,

              (float)clocks.PCLK1_Frequency/1000000,(float)clocks.PCLK2_Frequency/1000000,(float)clocks.ADCCLK_Frequency/1000000);

}

四、调试

4.1下载程序

按照上一章的接线图,将A9 A10接到DAP-Link虚拟串口的A2 A3上。

3.合宙Air32F103_USART_TIMER_第3张图片

 

4.2调试结果

复位后,打印当前的时钟频率,并且定时发送欢迎语句。

3.合宙Air32F103_USART_TIMER_第4张图片

 串口发送后将自动回复数据。

3.合宙Air32F103_USART_TIMER_第5张图片 发回的数据是在主函数中,进行处理的。

4.3控制LED

可以在处理的地方,添加对字符串的比较,对LED进行控制。

main.c

#include

#include

#include

#include "delay.h"

#include "led.h"

#include "usart.h"

#include "timer.h"

void CLK_Printf(void);

int main(void)

{

       delay_init();                                                                        //延时初始化

       uart1_init(115200);                                                      //串口1初始化

       TIM3_Int_Init(10000-1,72-1);               //定时器3初始化,10ms

//     TIM2_Int_Init(10000-1,36000-1);         //定时器2初始化,5000ms

       clear_usart1_buffer();                                           //清空串口1接受buffer

      

       CLK_Printf();                                                                            //打印时钟频率

      

       LED_GPIO_Init();                                                             //LED闪烁

      

       printf("wuzjjj\r\n");                                               //打印欢迎语句

       while (1)

       {

              if(USART1_RX_STA&0x8000)                         //收到串口数据

              {

                     if(strcmp((char*)USART1_RX_BUF,"LEDR_ON")==0)

                            LEDR_ON;

                     else if(strcmp((char*)USART1_RX_BUF,"LEDR_OFF")==0)

                            LEDR_OFF;

                     else if(strcmp((char*)USART1_RX_BUF,"LEDG_ON")==0)

                            LEDG_ON;

                     else if(strcmp((char*)USART1_RX_BUF,"LEDG_OFF")==0)

                            LEDG_OFF;

                     else if(strcmp((char*)USART1_RX_BUF,"LEDB_ON")==0)

                            LEDB_ON;

                     else if(strcmp((char*)USART1_RX_BUF,"LEDB_OFF")==0)

                            LEDB_OFF;

                     USART1_RX_STA = USART1_RX_STA&0x7FFF;             //去掉标志位,剩下数据长度

                     printf("received,%d:",USART1_RX_STA);        //发送辅助信息及收到的数据长度

                     printf("%s\r\n",USART1_RX_BUF);                                //将收到的数据发回

                     clear_usart1_buffer();                                                                //清空串口1接受buffer

              }

       }

}

void CLK_Printf(void)

{

       RCC_ClocksTypeDef clocks;

       RCC_GetClocksFreq(&clocks); //获取系统时钟频率

       printf("SYSCLK:%.1fMhz,HCLK:%.1fMhz,PCLK1:%.1fMhz,PCLK2:%.1fMhz,ADCCLK:%.1fMhz\r\n",

              (float)clocks.SYSCLK_Frequency/1000000,(float)clocks.HCLK_Frequency/1000000,

              (float)clocks.PCLK1_Frequency/1000000,(float)clocks.PCLK2_Frequency/1000000,(float)clocks.ADCCLK_Frequency/1000000);

}

编译后下载程序,使用串口助手发送如下命令,即可完成对LED的控制。

3.合宙Air32F103_USART_TIMER_第6张图片

 

你可能感兴趣的:(合宙Air32F103,合宙,嵌入式硬件,单片机,合宙Air32)