打印
[STM32F1]

实现呼吸灯效果---STM32f103C8t6

[复制链接]
692|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
PWM
1、框图
OC(Output Compare)输出比较
输出比较可以通过比较CNT和CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形
每个通用定时器和高级定时器都拥有4个输出比较通道
高级定时器的前三个通道额外拥有死区和互补输出的功能





使用特权

评论回复
沙发
一点点0321|  楼主 | 2024-1-29 19:34 | 只看该作者
二、TIM定时器映射

使用特权

评论回复
板凳
一点点0321|  楼主 | 2024-1-29 19:34 | 只看该作者
三、pwm介绍
SYSCLK(系统时钟)、 HCLK(由 AHB 预分频器直接输出得到)、 PCLK2(外设时钟,由 APB2 预分频器输出得到)、 PCLK1(外设时钟,由 APB1 预分频器输出得到) 这四个时钟的配置一般是: PCLK2 = HCLK= SYSCLK=PLLCLK = 72MHz, PCLK1=HCLK/2 = 36MHz。这个时钟配置也是库函数的标准配置,我们用的最多的就是这个。

使用特权

评论回复
地板
一点点0321|  楼主 | 2024-1-29 19:35 | 只看该作者
使用的是PWM1模式

使用特权

评论回复
5
一点点0321|  楼主 | 2024-1-29 19:35 | 只看该作者
开发板使能的灯是PB1

使用特权

评论回复
6
一点点0321|  楼主 | 2024-1-29 19:35 | 只看该作者
PB1对应的TIM3_CH4,位于APB1总线,而GPIOB位于APB2总线

使用特权

评论回复
7
一点点0321|  楼主 | 2024-1-29 19:36 | 只看该作者
二、主要文件

使用特权

评论回复
8
一点点0321|  楼主 | 2024-1-29 19:36 | 只看该作者
三、PWM初始化
1、使能PB1定时器3的通道4和IO口以及复用功能

2、外设的GPIO配置,TIM3_CH4选择输出比较通道4对应的GPIO配置是推挽复用输出模式

使用特权

评论回复
9
一点点0321|  楼主 | 2024-1-29 19:36 | 只看该作者
3、定时器配置

包括预分频值,寄存器周期值,时钟分隔(一般不分割),计数器模式

使用特权

评论回复
10
一点点0321|  楼主 | 2024-1-29 19:36 | 只看该作者
4、PWM1模式配置,TIM3通道4配置

包括定时器模式,输出比较状态,设置待装入捕获比较寄存器的脉冲值(设置比较值),输出极性(设置有效电平),使能通道,使能预装载寄存器,使能TIM3计数

使用特权

评论回复
11
一点点0321|  楼主 | 2024-1-29 19:36 | 只看该作者
四、代码
1、main.c

#include "pwm.h"
#include "led.h"
#include "delay.h"
#include <stm32f10x.h>
uint8_t CCR=50;
uint8_t state=0;
int main(void){
    led_init();
          pwm_Init();
          while(1){
            uint8_t k;
               switch(state){
                            case 0 :
                           k++;                           
                            if(k>=CCR)
                                                   state = 1;                       
                                 break;
                case        1:
                           k--;
                            if(k<=0)
                                                   state = 0;                                                         
                                 break;
                            default :   
                                       break;                               
                      }
                TIM_SetCompare4(TIM3,k);
                delay_ms(100);
     }
}

使用特权

评论回复
12
一点点0321|  楼主 | 2024-1-29 19:37 | 只看该作者
2、pwm.c
#include "pwm.h"


void pwm_Init(void){
          
          GPIO_InitTypeDef GPIO_InitStructure;
          TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
          TIM_OCInitTypeDef TIM_OCInitStructure;
          //PB0定时器3的通道4
          RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
                RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
          //配置,PB0的GPIO模式推挽复用输出模式
          GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
          GPIO_InitStructure.GPIO_Pin= GPIO_Pin_1;
          GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
          GPIO_Init(GPIOB,&GPIO_InitStructure);
          
                //定时器配置,产生频率,50Hz-60Hz  100Hz
          TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;//72MHz/7200=10000
                TIM_TimeBaseInitStructure.TIM_Period = 10000/100-1;           //计数范围0-99
          TIM_TimeBaseInitStructure.TIM_ClockDivision =0;
          TIM_TimeBaseInitStructure.TIM_CounterMode =TIM_CounterMode_Up;//向上计数模式
          TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
        //重映射先关掉JTAG引脚,先作为普通IO口
          //GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
                //GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);//重映射
        //
               
                /*
                PWM1模式配置:TIM3的通道3配置
CNT:计数值
CCR:比较值
REF:输出引脚参考电平
                PWM模式1 :向上计数:CNT<CCR,REF置有效电平,CNT>=CCR时,REF置无效电平
                           向下计数:CNT>CCR,REF置无效电平,CNT<=CCR时,REF置有效电平
                PWM模式2 :向上计数:CNT<CCR,REF置无效电平,CNT>=CCR时,REF置有效电平
                           向下计数:CNT>CCR,REF置有效电平,CNT<=CCR时,REF置无效电平
                */
               
                TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1 ;
                TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//PWM输出使能
                TIM_OCInitStructure.TIM_Pulse = CCR;//设置比较值,比较值决定占空比 值的范围由计数值决定
                TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High ;//有效电平为高电平
                TIM_OC4Init(TIM3, &TIM_OCInitStructure);//0-50-99,0-55的值为高电平,>55的为低电平       
                //使能预装载寄存器
                TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable);
                //使能自动重装载寄存器
                TIM_ARRPreloadConfig(TIM3,ENABLE);
                //使能TIM3计数
                TIM_Cmd(TIM3,ENABLE);  
}

使用特权

评论回复
13
一点点0321|  楼主 | 2024-1-29 19:37 | 只看该作者
2、pwm.c
#include "pwm.h"


void pwm_Init(void){
          
          GPIO_InitTypeDef GPIO_InitStructure;
          TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
          TIM_OCInitTypeDef TIM_OCInitStructure;
          //PB0定时器3的通道4
          RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
                RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
          //配置,PB0的GPIO模式推挽复用输出模式
          GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
          GPIO_InitStructure.GPIO_Pin= GPIO_Pin_1;
          GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
          GPIO_Init(GPIOB,&GPIO_InitStructure);
          
                //定时器配置,产生频率,50Hz-60Hz  100Hz
          TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;//72MHz/7200=10000
                TIM_TimeBaseInitStructure.TIM_Period = 10000/100-1;           //计数范围0-99
          TIM_TimeBaseInitStructure.TIM_ClockDivision =0;
          TIM_TimeBaseInitStructure.TIM_CounterMode =TIM_CounterMode_Up;//向上计数模式
          TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
        //重映射先关掉JTAG引脚,先作为普通IO口
          //GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
                //GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);//重映射
        //
               
                /*
                PWM1模式配置:TIM3的通道3配置
CNT:计数值
CCR:比较值
REF:输出引脚参考电平
                PWM模式1 :向上计数:CNT<CCR,REF置有效电平,CNT>=CCR时,REF置无效电平
                           向下计数:CNT>CCR,REF置无效电平,CNT<=CCR时,REF置有效电平
                PWM模式2 :向上计数:CNT<CCR,REF置无效电平,CNT>=CCR时,REF置有效电平
                           向下计数:CNT>CCR,REF置有效电平,CNT<=CCR时,REF置无效电平
                */
               
                TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1 ;
                TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//PWM输出使能
                TIM_OCInitStructure.TIM_Pulse = CCR;//设置比较值,比较值决定占空比 值的范围由计数值决定
                TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High ;//有效电平为高电平
                TIM_OC4Init(TIM3, &TIM_OCInitStructure);//0-50-99,0-55的值为高电平,>55的为低电平       
                //使能预装载寄存器
                TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable);
                //使能自动重装载寄存器
                TIM_ARRPreloadConfig(TIM3,ENABLE);
                //使能TIM3计数
                TIM_Cmd(TIM3,ENABLE);  
}

使用特权

评论回复
14
一点点0321|  楼主 | 2024-1-29 19:37 | 只看该作者
3、pwm.h
#ifndef _PWM_H
#define _PWM_H
#include <stm32f10x.h>
#include <delay.h>

extern uint8_t CCR;


void pwm_Init(void);

#endif

使用特权

评论回复
15
一点点0321|  楼主 | 2024-1-29 19:37 | 只看该作者
4、led.c
#include <led.h>
uint8_t i,j,l;
void led_init()
{
   GPIO_InitTypeDef GPIO_InitStructure;
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA,ENABLE);
   GPIO_InitStructure.GPIO_Pin=LED_PIN|LED1_PIN|LED2_PIN|LED3_PIN|LED4_PIN;
         GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
         GPIO_InitStructure.GPIO_Speed =GPIO_Speed_2MHz;
       
   GPIO_Init(LED_PORT,&GPIO_InitStructure);         
         GPIO_Init(LED1_PORT,&GPIO_InitStructure);
         GPIO_Init(LED2_PORT,&GPIO_InitStructure);
         GPIO_Init(LED3_PORT,&GPIO_InitStructure);
         GPIO_Init(LED4_PORT,&GPIO_InitStructure);
}


void led_display()
{
  for(i=0;i<5;i++)
  {
          LED_ON();
                delay_ms(1000);
          LED_OFF();
                delay_ms(1000);
          LED1_ON();
                delay_ms(1000);
                LED1_OFF();
                delay_ms(1000);
                LED2_ON();
                delay_ms(1000);
                LED2_OFF();
                delay_ms(1000);
                LED3_ON();
                delay_ms(1000);
                LED3_OFF();
                delay_ms(1000);
        }
}
void led_run1()
{
   for(j=0;j<5;j++)
         {
          
                   // LED1_ON();delay_ms(100);LED1_OFF();
                          LED2_ON();delay_ms(100);LED2_OFF();
                          LED3_ON();delay_ms(100);LED3_OFF();
                          LED4_ON();delay_ms(100);LED4_OFF();         
         }
}
void led_run2()
{
   for(l=0;l<5;l++)
         {
          
                    //LED1_ON();delay_ms(100);
                          LED2_ON();delay_ms(100);
                          LED3_ON();delay_ms(100);
                          LED4_ON();delay_ms(100);
                    LED1_OFF();LED2_OFF();LED3_OFF();LED4_OFF();       
         }
}

使用特权

评论回复
16
一点点0321|  楼主 | 2024-1-29 19:37 | 只看该作者
5、led.h
#ifndef _LED_H
#define _LED_H
#include <stm32f10x.h>
#include <delay.h>

#define LED_PORT GPIOC
#define LED_PIN GPIO_Pin_13

#define LED_ON()  GPIO_ResetBits(LED_PORT,LED_PIN)
#define LED_OFF() GPIO_SetBits(LED_PORT,LED_PIN)

#define LED1_PORT GPIOB
#define LED1_PIN  GPIO_Pin_0

#define LED2_PORT GPIOB
#define LED2_PIN  GPIO_Pin_1

#define LED3_PORT GPIOA
#define LED3_PIN  GPIO_Pin_8

#define LED4_PORT GPIOB
#define LED4_PIN  GPIO_Pin_14

#define LED1_ON()   GPIO_SetBits(LED1_PORT,LED1_PIN)
#define LED1_OFF()  GPIO_ResetBits(LED1_PORT,LED1_PIN)

#define LED2_ON()   GPIO_SetBits(LED2_PORT,LED2_PIN)
#define LED2_OFF()  GPIO_ResetBits(LED2_PORT,LED2_PIN)

#define LED3_ON()   GPIO_SetBits(LED3_PORT,LED3_PIN)
#define LED3_OFF()  GPIO_ResetBits(LED3_PORT,LED3_PIN)

#define LED4_ON()   GPIO_SetBits(LED4_PORT,LED4_PIN)
#define LED4_OFF()  GPIO_ResetBits(LED4_PORT,LED4_PIN)

void led_init(void);
void led_display(void);
void led_run1(void);       
void led_run2(void);       
#endif

使用特权

评论回复
17
一点点0321|  楼主 | 2024-1-29 19:38 | 只看该作者
6、delay.c
#include <delay.h>

void delay_ms(uint32_t i)
{
   u32 temp;
         SysTick->LOAD=9000*i;
         SysTick->CTRL=0x01;
         SysTick->VAL=0;
        do
        {
           temp=SysTick->CTRL;
        }
        while((temp&0x01)&&(!(temp&(1<<16))));
        SysTick->CTRL=0;
        SysTick->VAL=0;
}

使用特权

评论回复
18
一点点0321|  楼主 | 2024-1-29 19:38 | 只看该作者
7、delay.h
#ifndef  _DELAY_H
#define  _DELAY_H
#include <stm32f10x.h>

void delay_ms(uint32_t i);

#endif

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

48

主题

389

帖子

0

粉丝