新手上路
- 积分
- 34
- 金钱
- 34
- 注册时间
- 2018-1-31
- 在线时间
- 10 小时
|
15金钱
想输出200HZ的pwm信号,但是分频系数是u16类型的,最高就65536,合起来pwm信号频率最低1098hz,所有?只能用定时器?做一个假的pwm输出?
timer.c里:
u32 times = 0;
extern u16 realtimes;
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 = 0; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIMx
}
void TIM4_Int_Init(u16 arr, u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //声明一个结构体变量,用来初始化GPIO
NVIC_InitTypeDef NVIC_InitStructure;
/* 开启定时器4时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
TIM_ClearITPendingBit(TIM4,TIM_IT_Update);//清除TIMx的中断待处理位:TIM 中断源
TIM_TimeBaseInitStructure.TIM_Period = arr;//设置自动重装载寄存器周期的值
TIM_TimeBaseInitStructure.TIM_Prescaler = psc;//设置用来作为TIMx时钟频率预分频值,100Khz计数频率
TIM_TimeBaseInitStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM向上计数模式
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);
TIM_Cmd(TIM4,DISABLE); //使能或者失能TIMx外设
/* 设置中断参数,并打开中断 */
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE ); //使能或者失能指定的TIM中断
/* 设置NVIC参数 */
NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn; //打开TIM3_IRQn的全局中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; //抢占优先级为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority=3; //响应优先级为1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM4, ENABLE); //使能TIMx
}
//定时器3中断服务程序
void TIM3_IRQHandler(void) //TIM3中断
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx更新中断标志
if(times > 1000)//防止溢出错误
times = 0;
else
times++;
}
}
void TIM4_IRQHandler(void) //TIM3中断
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update ); //清除TIMx更新中断标志
LED0 = 0;
times = 0;
while(times < realtimes) //总时间长度为realtimes*10us
;
LED0 = 1;
}
}
main函数:
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "timer.h"
#include "lcd.h"
u8 x = 0;
u8 lcd_id[12]; //存放LCD ID字符串
u16 s = 1;
u16 t;
u16 len;
u16 tem;
u16 realtimes=0;
int main(void)
{
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
LED_Init(); //LED端口初始化
LCD_Init();
TIM3_Int_Init(1-1,72-1);//100Khz的计数频率,计数到1为10us
TIM4_Int_Init(100-1,7200-1);//保证10ms触发一次
while(1)
{
if(USART_RX_STA&0x8000)//1000 0000 0000 0000,收到消息时执行
{
len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度0011 1111 1111 1111
if(USART_RX_BUF[0] == '+') //整个判断语句会把串口的信息转换成数值放到realtimes,如+10,会在原realtimes值+10,直接输入33会把realtimes值置成33
{
tem = 0;
s = 1;
for(t = len - 1;t > 0;t--)
{
tem += (USART_RX_BUF[t] - 48)*s;
s *= 10;
}
realtimes += tem;
if(realtimes>200)
realtimes=200;
}
else if(USART_RX_BUF[0] == '-')
{
tem = realtimes;
s = 1;
for(t = len - 1;t > 0;t--)
{
if(tem < (USART_RX_BUF[t] - 48)*s){
tem = 0;
t = 1;
}
else
tem -= (USART_RX_BUF[t] - 48)*s;
s *= 10;
}
realtimes = tem;
}
else
{
tem = 0;
s = 1;
for(t = len - 1;t > 0;t--)
{
tem += (USART_RX_BUF[t] - 48)*s;
s *= 10;
}
tem += (USART_RX_BUF[0] - 48)*s;
realtimes = tem;
if(realtimes>200)
realtimes=200;
}
USART_RX_STA=0;
}
x=realtimes/100;
lcd_id[0]=(u8) (x+'0');
x=(realtimes%100)/10;
lcd_id[1]=(u8) (x+'0');
x=realtimes%10;
lcd_id[2]=(u8) (x+'0');
lcd_id[3]='\0';
LCD_ShowString(30,40,210,24,24,"The PWM value:");
LCD_ShowString(108,100,200,16,16,lcd_id); //显示LCD ID
}
但是程序运行时非常容易卡死,为什么?比如定时向串口+1,一定会在某个时刻卡死,而且有的是raeltimes的值会跳变,可是如果禁用时钟中断,realtimes的值不会跳变的
|
|