按键控制输出占空比可调的PWM波

这里写自定义目录标题

  • 按键的误区
    • 举个例子
    • 代码如下
    • 实验结果
    • 如何插入一段漂亮的代码片
    • 生成一个适合你的列表
    • 创建一个表格
      • 设定内容居中、居左、居右
      • SmartyPants
    • 创建一个自定义列表
    • 如何创建一个注脚
    • 注释也是必不可少的
    • KaTeX数学公式
    • 新的甘特图功能,丰富你的文章
    • UML 图表
    • FLowchart流程图
    • 导出与导入
      • 导出
      • 导入

按键的误区

	按键有很多种,按下到放开,一直按。。。。。。一般大家都喜欢用delay()这个延时程序,但有时会碰到很多问题,delay()是不精准延时,按键按下的时候存在抖动,不可能说每次都能很准确地消抖。所以说有时候写的代码达不到预期的效果。

举个例子

	在做按键控制输出占空比可调的PWM波时,因为存在delay(),输出波形要等delay()之后才输出。delay()一次的时间可能你设置了20ms,但是你不知道按键按下到弹起之间上升沿和下降沿切换了多少次,不知道有没有完全消抖。所以在按键切换波形的时候会发生误按:按一下可能刚好是一下,也可能是2下,3下,是一个随机数了。为了解决这个问题,我们只需要将按键的高/低电平一直持续到我们放开按键的时刻就可以解决了。

代码如下

main.c

#include “stm32f10x.h”
#include “bsp_advancetime.h”
#include “bsp_key.h”
#include “bsp_led.h”
uint16_t Value;

int main(void)
{

Value=5;		//设置初始脉宽为5
LED_GPIO_Config();		//LED初始化
Key_GPIO_Config();		//按键初始化
Advance_Time_Config();		//输出初始化波形,脉宽为5
while(1)
{
	if(Key_Scan(GPIOA,GPIO_Pin_0)==KEY_ON)		//如果按键按下
	{
		Value=Value-1;		
		if(Value==0)		//如果脉宽=0的时候切换回5
		{
			Value=5;
		}
		Advance_Time_Config();		//输出波形
		LED1_TOGGLE;		//LED1状态翻转

	}
}

}

bsp_advancetime.c

#include “bsp_advancetime.h”
#include “bsp_key.h”
extern uint16_t Value;

void Advance_Time_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;

/*输出比较通道初始化*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;		/*复用推挽输出*/
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);

/*输出比较通道互补通道初始化*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_13;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);

/*输出比较通道刹车通道初始化*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_12;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);

/*BKIN引脚默认输出低电平		为1时表示刹车*/
GPIO_ResetBits(GPIOB,GPIO_Pin_12);

}

void Advance_Time_Mode_Config(void)
{
/开启TIM1时钟/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
/时基结构体初始化配置/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
/ARR的值 时钟周期/
TIM_TimeBaseInitStruct.TIM_Period=7;
/72M时钟的预分频数 提供给计数器计数/
TIM_TimeBaseInitStruct.TIM_Prescaler=8;
/不启动重复计数/
TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;
/配置死区时间用/
TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;
/计数器为向上计数模式/
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
/时基结构体初始化/
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);

/*输出比较结构体初始化*/
TIM_OCInitTypeDef TIM_OCInitStruct;
/*输出模式配置为PWM1*/
TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;
/*输出使能*/
TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
/*互补输出使能*/
TIM_OCInitStruct.TIM_OutputNState=TIM_OutputNState_Enable;
/*Pulse/Period+1*/
TIM_OCInitStruct.TIM_Pulse=Value;		/*Pulse实际改变的是CCR的值		当CNT计数到CCR时,电平发生一次翻转*/
/*输出通道为高电平有效*/
TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
/*空闲状态时,经过死区时间后为低电平*/
TIM_OCInitStruct.TIM_OCIdleState=TIM_OCIdleState_Reset;
/*输出比较结构体初始化*/
TIM_OC1Init(TIM1, &TIM_OCInitStruct);
/*使能预装载CCR1*/
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
/*使能计数器*/
TIM_Cmd(TIM1,ENABLE);
// 主输出使能,当使用的是通用定时器时,这句不需要
TIM_CtrlPWMOutputs(TIM1, ENABLE);

}

void Advance_Time_Config(void)
{
Advance_Time_GPIO_Config();
Advance_Time_Mode_Config();
}

bsp_advancetime.h

#ifndef _BSP_ADVANCETIME_H
#define _BSP_ADVANCETIME_H
#include “stm32f10x.h”

void Advance_Time_GPIO_Config(void);
void Advance_Time_Mode_Config(void);
void Advance_Time_Config(void);
#endif /_BSP_ADVANCETIME_H/

bsp_key.c

#include “bsp_key.h”

void Key_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA,&GPIO_InitStruct);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_13;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOC,&GPIO_InitStruct);

}

uint8_t Key_Scan(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin)
{
/*检测是否有按键按下 */
if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON )
{
/*等待按键释放 */
while(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON);
return KEY_ON;
}
else
return KEY_OFF;
}

bsp_key.h

#ifndef _BSP_KEY_H
#define _BSP_KEY_H

#include “stm32f10x.h”
#define KEY_ON 1
#define KEY_OFF 0
void Key_GPIO_Config(void);
uint8_t Key_Scan(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin);

#endif /_BSP_KEY_H/

bsp_led.c

#include “bsp_led.h”

void LED_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_2;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_SetBits(GPIOC,GPIO_Pin_2);
GPIO_Init(GPIOC,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_3;
GPIO_SetBits(GPIOC,GPIO_Pin_3);
GPIO_Init(GPIOC,&GPIO_InitStruct);
}

bsp_led.h

#ifndef _BSP_LED_H
#define _BSP_LED_H
#include “stm32f10x.h”

/* 定义控制IO的宏 */
#define LED1_TOGGLE digitalToggle(GPIOC,GPIO_Pin_2)
#define LED1_OFF digitalHi(GPIOC,GPIO_Pin_2)
#define LED1_ON digitalLo(GPIOC,GPIO_Pin_2)

#define LED2_TOGGLE digitalToggle(GPIOC,GPIO_Pin_3)
#define LED2_OFF digitalHi(GPIOC,GPIO_Pin_3)
#define LED2_ON digitalLo(GPIOC,GPIO_Pin_3)

/* 直接操作寄存器的方法控制IO */
#define digitalHi(p,i) {p->BSRR=i;} //输出为高电平
#define digitalLo(p,i) {p->BRR=i;} //输出低电平
#define digitalToggle(p,i) {p->ODR ^=i;} //输出反转状态

void LED_GPIO_Config(void);
#endif /_BSP_LED_H/

实验结果

链接: link.

图片:
按键控制输出占空比可调的PWM波_第1张图片
依次类推
按键控制输出占空比可调的PWM波_第2张图片按键控制输出占空比可调的PWM波_第3张图片

如何插入一段漂亮的代码片

去博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

// An highlighted block
var foo = 'bar';

生成一个适合你的列表

  • 项目
    • 项目
      • 项目
  1. 项目1
  2. 项目2
  3. 项目3
  • 计划任务
  • 完成任务

创建一个表格

一个简单的表格是这么创建的:

项目 Value
电脑 $1600
手机 $12
导管 $1

设定内容居中、居左、居右

使用:---------:居中
使用:----------居左
使用----------:居右

第一列 第二列 第三列
第一列文本居中 第二列文本居右 第三列文本居左

SmartyPants

SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:

TYPE ASCII HTML
Single backticks 'Isn't this fun?' ‘Isn’t this fun?’
Quotes "Isn't this fun?" “Isn’t this fun?”
Dashes -- is en-dash, --- is em-dash – is en-dash, — is em-dash

创建一个自定义列表

Markdown
Text-to- HTML conversion tool
Authors
John
Luke

如何创建一个注脚

一个具有注脚的文本。1

注释也是必不可少的

Markdown将文本转换为 HTML

KaTeX数学公式

您可以使用渲染LaTeX数学表达式 KaTeX:

Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n1)!nN 是通过欧拉积分

Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t   . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=0tz1etdt.

你可以找到更多关于的信息 LaTeX 数学表达式here.

新的甘特图功能,丰富你的文章

Mon 06 Mon 13 Mon 20 已完成 进行中 计划一 计划二 现有任务 Adding GANTT diagram functionality to mermaid
  • 关于 甘特图 语法,参考 这儿,

UML 图表

可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图::

张三 李四 王五 你好!李四, 最近怎么样? 你最近怎么样,王五? 我很好,谢谢! 我很好,谢谢! 李四想了很长时间, 文字太长了 不适合放在一行. 打量着王五... 很好... 王五, 你怎么样? 张三 李四 王五

这将产生一个流程图。:

链接
长方形
圆角长方形
菱形
  • 关于 Mermaid 语法,参考 这儿,

FLowchart流程图

我们依旧会支持flowchart的流程图:

Created with Raphaël 2.2.0 开始 我的操作 确认? 结束 yes no
  • 关于 Flowchart流程图 语法,参考 这儿.

导出与导入

导出

如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。

导入

如果你想加载一篇你写过的.md文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。


  1. 注脚的解释 ↩︎

你可能感兴趣的:(STM32)