OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2689|回复: 9

我的代码哪里错了?怎么用stm32f1系列输出可控制的200HZ pwm信号?

[复制链接]

7

主题

33

帖子

0

精华

新手上路

积分
34
金钱
34
注册时间
2018-1-31
在线时间
10 小时
发表于 2018-2-6 09:12:26 | 显示全部楼层 |阅读模式
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的值不会跳变的

最佳答案

查看完整内容[请看2#楼]

200HZ PWM模式完全可以 你这个定时器 感觉有点复杂
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

9

主题

86

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
211
金钱
211
注册时间
2017-6-16
在线时间
46 小时
发表于 2018-2-6 09:12:27 | 显示全部楼层
200HZ  PWM模式完全可以   你这个定时器 感觉有点复杂
回复

使用道具 举报

5

主题

184

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1050
金钱
1050
注册时间
2016-5-13
在线时间
111 小时
发表于 2018-2-6 09:27:44 | 显示全部楼层
本帖最后由 zhuifeng8911 于 2018-2-6 09:30 编辑

200Hz的PWM随便就输出来的,你要分频系数和计数值配合好。比如你24分频,15000的计数值
回复

使用道具 举报

4

主题

349

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1046
金钱
1046
注册时间
2017-5-19
在线时间
335 小时
发表于 2018-2-6 09:37:21 | 显示全部楼层
用PWM模式,中断要写的简洁,中断里延时一般情况是不允许的
回复

使用道具 举报

7

主题

33

帖子

0

精华

新手上路

积分
34
金钱
34
注册时间
2018-1-31
在线时间
10 小时
 楼主| 发表于 2018-2-6 09:42:29 | 显示全部楼层
zhuifeng8911 发表于 2018-2-6 09:27
200Hz的PWM随便就输出来的,你要分频系数和计数值配合好。比如你24分频,15000的计数值

哦,看来是我理解错了,我以为
void TIM3_PWM_Init(u16 arr,u16 psc)里第1个产生决定频率,第2个必须为0。
回复

使用道具 举报

3

主题

1155

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
7464
金钱
7464
注册时间
2015-1-15
在线时间
1368 小时
发表于 2018-2-6 13:39:56 | 显示全部楼层
一个定时器的事情,偏偏用两个;
一分耕耘一分收获。
回复

使用道具 举报

7

主题

33

帖子

0

精华

新手上路

积分
34
金钱
34
注册时间
2018-1-31
在线时间
10 小时
 楼主| 发表于 2018-2-6 15:57:58 | 显示全部楼层
本帖最后由 xingshou 于 2018-2-7 13:24 编辑
yklstudent 发表于 2018-2-6 13:39
一个定时器的事情,偏偏用两个;

what?
回复

使用道具 举报

3

主题

1155

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
7464
金钱
7464
注册时间
2015-1-15
在线时间
1368 小时
发表于 2018-2-6 19:19:04 | 显示全部楼层
xingshou 发表于 2018-2-6 15:57
you can you up, no can no BB.

中国人说中国话,假洋鬼子死滚
一分耕耘一分收获。
回复

使用道具 举报

0

主题

64

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
249
金钱
249
注册时间
2018-1-19
在线时间
28 小时
发表于 2018-2-6 19:37:05 | 显示全部楼层
还行吧?我近期就是用32做的, 不过是HAL版本的额
回复

使用道具 举报

4

主题

349

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1046
金钱
1046
注册时间
2017-5-19
在线时间
335 小时
发表于 2018-2-7 09:39:27 | 显示全部楼层
yklstudent 发表于 2018-2-6 19:19
中国人说中国话,假洋鬼子死滚

现在,提问的都是大爷
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-9 05:12

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表