完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
这里介绍两种方式使用STM32的定时器:直接操作寄存器和使用st的官方的库文件。 相比较而言,直接操作定时器比较简洁,对着寄存器看十分明了。而使用库文件有一点晕头转向。 (个人观点) 程序如下:(以下程序在DX32的例程修改而来,使用的是比较古老的3.0固件库) 1、timer.c文件 #include "STM32Lib\stm32f10x.h" void TIM2_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; u16 CCR1_Val = 4000; u16 CCR2_Val = 2000; u16 CCR3_Val = 1000; u16 CCR4_Val = 500; /* TIM2 clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); /* 基础设置*/ TIM_TimeBaseStructure.TIM_Period = 10000; //计满值 TIM_TimeBaseStructure.TIM_Prescaler = 7200-1; //预分频,此值+1为分频的除数 TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; // TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); /* 比较通道1*/ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive; //输出比较非主动模式 TIM_OCInitStructure.TIM_Pulse = CCR1_Val; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //极性为正 TIM_OC1Init(TIM2, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable); //禁止OC1重装载,其实可以省掉这句,因为默认是4路都不重装的. /*比较通道2 */ TIM_OCInitStructure.TIM_Pulse = CCR2_Val; TIM_OC2Init(TIM2, &TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable); /* 比较通道3 */ TIM_OCInitStructure.TIM_Pulse = CCR3_Val; TIM_OC3Init(TIM2, &TIM_OCInitStructure); TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable); /* 比较通道4 */ TIM_OCInitStructure.TIM_Pulse = CCR4_Val; TIM_OC4Init(TIM2, &TIM_OCInitStructure); TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Disable); /*使能预装载*/ TIM_ARRPreloadConfig(TIM2, ENABLE); /*预先清除所有中断位*/ TIM_ClearITPendingBit(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4|TIM_IT_Update); /* 4个通道和溢出都配置中断*/ TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4|TIM_IT_Update, ENABLE); /* 允许TIM2开始计数 */ TIM_Cmd(TIM2, ENABLE); } void TIM3_Configuration(u16 p,u16 psc) { RCC->APB1ENR|=1<<1;//TIM3时钟使能 //自动装载寄存器 TIM3->ARR=p; //设定定时器自动重装值 //PSC预分频寄存器 TIM3->PSC=psc; //设定定时器的分频系数 TIM3->DIER|=1<<0; //允许更新中断 TIM3->DIER|=1<<6; //允许触发中断 TIM3->CR1|=0X01; //使能定时器3(这里面包括计数方向为向上计数) } #if 0 void TIM4_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; /* TIM4 clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); /* 基础设置*/ TIM_TimeBaseStructure.TIM_Period = 10000; //计满值 TIM_TimeBaseStructure.TIM_Prescaler = 7200-1; //预分频,此值+1为分频的除数 TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; // TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数 TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); /*使能预装载*/ TIM_ARRPreloadConfig(TIM4, ENABLE); /*预先清除所有中断位*/ TIM_ClearITPendingBit(TIM4, TIM_IT_Update); TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE); /* 允许TIM2开始计数 */ TIM_Cmd(TIM4, ENABLE); } #else void TIM_Configuration(u16 p,u16 psc) { RCC->APB1ENR|=1<<2;//TIM4时钟使能 //自动装载寄存器 TIM4->ARR=p; //设定定时器自动重装值 //PSC预分频寄存器 TIM4->PSC=psc; //设定定时器的分频系数 TIM4->DIER|=1<<0; //允许更新中断 TIM4->DIER|=1<<6; //允许触发中断 TIM4->CR1|=0X01; //使能定时器3(这里面包括计数方向为向上计数) } #endif 上程序中,定时器2被配置成多路捕获模式,定时器3是直接操作寄存器进行配置的。 定时器4用了两种配置方式,使用固件库和直接操作寄存器。可以切换。效果一样。 需要注意的是,stm32103RBT6的通用定时器只有2、3、4.(没有5) 2、stm32f10x_it.c文件 /******************************************************************************* * Function Name : TIM2_IRQHandler TIM2中断 * Description : This function handles TIM2 global interrupt request. * Input : None * Output : None * Return : None *******************************************************************************/ unsigned int cnt=0; unsigned int flag=0; void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) { /*必须清空标志位*/ TIM_ClearITPendingBit(TIM2, TIM_IT_CC1); //可添加功能块...... } else if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_CC2); //可添加功能块...... } else if (TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_CC3); //可添加功能块...... } else if (TIM_GetITStatus(TIM2, TIM_IT_CC4) != RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_CC4); //可添加功能块...... } if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //flag=1;//计时满标志位置位 //cnt++;//每TIM_Period计时满变量加一 } } /******************************************************************************* * Function Name : TIM3_IRQHandler * Description : This function handles TIM3 global interrupt request. * Input : None * Output : None * Return : None *******************************************************************************/ void TIM3_IRQHandler(void) { if(TIM3->SR&0X0001) { cnt++; flag=1; } TIM3->SR&=~(1<<0); } /******************************************************************************* * Function Name : TIM4_IRQHandler * Description : This function handles TIM4 global interrupt request. * Input : None * Output : None * Return : None *******************************************************************************/ void TIM4_IRQHandler(void) { if(TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM4, TIM_IT_Update); cnt++; flag=1; } } 可以看到,定时器2有多个处理的事件,四个通道的计数溢出和定时器的总溢出。具体事件根据应用来配置。 另外,以上代码只是对三个通用定时器进行测试,具体应用根据情况来定。 3、NVIC.c文件 #include "STM32Lib\stm32f10x.h" //设置所有的中断允许 void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; /* Timer2中断*/ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); #if 1 /* Configure one bit for preemption priority */ /* Timer3中断*/ NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* Timer4中断*/ NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); #endif /*UART1*/ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } 4、main.c文件 #include "STM32Lib\stm32f10x.h" #include "hal.h" #include "stdio.h" #include "string.h" extern unsigned int cnt; extern unsigned int flag; int fputc(int ch, FILE *f) { //USART_SendData(USART1, (u8) ch); USART1->DR = (u8) ch; /* Loop until the end of transmission */ while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET) { } return ch; } int main(void) { CanTxMsg msg; msg.StdId=0x11; msg.DLC=8; msg.IDE=CAN_ID_STD; msg.RTR=CAN_RTR_DATA; memset(msg.Data,0x11,8); ChipHalInit(); //片内硬件初始化 ChipOutHalInit(); //片外硬件初始化 for(;;) { can_send(&msg); if(flag) { flag=0; printf("cnt is %dn",cnt); } } } 本程序使用了串口、定时器,通过串口将当前计数值发给PC。 同时通过can总线对外发送数据 另外使用了printf,程序中有相应的配置。 5、can.c文件 #include "STM32Lib\stm32f10x.h" #include "hal.h" #include //CAN总线的发送接收管脚的初始化 void CAN_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE); //RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* PA11-CAN RX */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOA, &GPIO_InitStructure); /*PA12-CAN TX */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); // RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); } /******************************************************************************* **CAN中断测试 *******************************************************************************/ void CAN_Interrupt(void) { CAN_InitTypeDef CAN_InitStructure; CAN_FilterInitTypeDef CAN_FilterInitStructure; // CanTxMsg TxMessage; /* CAN register init */ CAN_DeInit(CAN1); CAN_StructInit(&CAN_InitStructure); /* CAN cell init */ /* CAN cell init */ CAN_InitStructure.CAN_TTCM=DISABLE; //时间触发 CAN_InitStructure.CAN_ABOM=DISABLE; //自动离线管理 CAN_InitStructure.CAN_AWUM=DISABLE; //自动唤醒 CAN_InitStructure.CAN_NART=DISABLE; //ENABLE:错误不自动重传 DISABLE:重传 CAN_InitStructure.CAN_RFLM=DISABLE; CAN_InitStructure.CAN_TXFP=DISABLE; CAN_InitStructure.CAN_Mode=CAN_Mode_Normal; //CAN_Mode_LoopBack,CAN_Mode_Normal CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; //1-4 CAN_InitStructure.CAN_BS1=CAN_BS1_5tq; //1-16 CAN_InitStructure.CAN_BS2=CAN_BS2_3tq; //1-8 CAN_InitStructure.CAN_Prescaler=4; //波特率为 36/(4*(1+5+3))=1000k CAN_Init(CAN1,&CAN_InitStructure); /* CAN 过滤器设置 */ CAN_FilterInitStructure.CAN_FilterNumber=0; CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; CAN_FilterInitStructure.CAN_FilterIdLow=0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000; CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0; CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; CAN_FilterInit(&CAN_FilterInitStructure); /* 允许FMP0中断*/ CAN_ITConfig(CAN1,CAN_IT_FMP0, ENABLE); }/* typedef struct { uint32_t StdId; uint32_t ExtId; uint8_t IDE; uint8_t RTR; uint8_t DLC; uint8_t Data[8]; } CanTxMsg; */ //发送一个2字节的数据 void SendCan(u16 dat) { CanTxMsg TxMessage; TxMessage.ExtId=0x01; TxMessage.IDE=CAN_ID_EXT; TxMessage.RTR=CAN_RTR_DATA; TxMessage.DLC=2; TxMessage.Data[0]=dat&0xff; TxMessage.Data[1]=dat>>8; CAN_Transmit(CAN1,&TxMessage); } #if 1 int can_send(CanTxMsg *pTransmitBuf) { u8 TransmitMailbox=0; CanTxMsg TxMessage; if(pTransmitBuf -> DLC > 8) { return 1; } /* transmit */ TxMessage.StdId=pTransmitBuf ->StdId;//用来设定标准标识符(0-0x7ff,11位) //TxMessage.ExtId=pTransmitBuf ->ExtId; TxMessage.RTR= pTransmitBuf ->RTR;//设置RTR位为数据帧 TxMessage.IDE= pTransmitBuf ->IDE;//标识符扩展位,为标准帧 TxMessage.DLC= pTransmitBuf ->DLC;//设置数据长度 //根据DLC字段的值,将有效数据拷贝到发送数据寄存器 memcpy(TxMessage.Data, pTransmitBuf ->Data,pTransmitBuf ->DLC); TransmitMailbox = CAN_Transmit(CAN1,&TxMessage); TransmitMailbox=TransmitMailbox;//加上这句话就是防止编译器产生警告 return 1; } #endif 在调用can_send(CanTxMsg *pTransmitBuf)发送数据之前,要对can总线进行相应的配置。 6、hal.c文件 /*************************************************** **HAL.c **主要用于芯片硬件的内部外围和外部外围的初始化,两大INIT函数 **在MAIN中调用,使MAIN函数中尽量与硬件库无关 ***************************************************/ //STM32F103RBT6有三个通用定时器,定时器2、3、4;操作基本一致 #include "STM32Lib\stm32f10x.h" //各个内部硬件模块的配置函数 extern void GPIO_Configuration(void); //GPIO extern void RCC_Configuration(void); //RCC extern void USART_Configuration(void); //串口 extern void NVIC_Configuration(void); //NVIC extern void TIM2_Configuration(void); extern void TIM3_Configuration(u16 p,u16 psc); extern void TIM4_Configuration(void); extern void TIM_Configuration(u16 p,u16 psc); extern void CAN_Configuration(void); extern void CAN_Interrupt(void); /******************************* **函数名:ChipHalInit() **功能:片内硬件初始化 *******************************/ void ChipHalInit(void) { //初始化时钟源 RCC_Configuration(); //初始化GPIO GPIO_Configuration(); //初始化中断源 NVIC_Configuration(); //初始化串口 USART_Configuration(); //初始化定时器 //TIM2_Configuration(); // //TIM3_Configuration(10000,7199); //TIM4_Configuration(); TIM_Configuration(10000,7199); //初始化CAN总线 CAN_Configuration(); //初始化CAN总线接收中断 CAN_Interrupt(); } /********************************* **函数名:ChipOutHalInit() **功能:片外硬件初始化 *********************************/ void ChipOutHalInit(void) { } |
|
相关推荐
1 个讨论
|
|
你正在撰写讨论
如果你是对讨论或其他讨论精选点评或询问,请使用“评论”功能。
1470 浏览 1 评论
AD7686芯片不传输数据给STM32,但是手按住就会有数据。
1405 浏览 3 评论
3150 浏览 0 评论
如何解决MPU-9250与STM32通讯时,出现HAL_ERROR = 0x01U
1543 浏览 1 评论
hal库中i2c卡死在HAL_I2C_Master_Transmit
1975 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-4 15:44 , Processed in 0.633257 second(s), Total 42, Slave 34 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号