一个小项目

编程入门 行业动态 更新时间:2024-10-27 04:23:49

一个小<a href=https://www.elefans.com/category/jswz/34/1771421.html style=项目"/>

一个小项目

基于stm32的小台灯

  • 一、前言
  • 二、所需模块
  • 三、代码
  • 四、成品

一、前言

  由于各位对于的单片机较为生疏,在此我再仔细介绍一下单片机。
  俗话说,以项目驱动学习,才是学习快速的秘诀
通过一次次的项目才能更加对某一个东西熟悉。
  废话不多说,直接开始做
如果对单片机不熟悉的话,可以看我的另一篇blog(虽然还没更完)

二、所需模块

一个stm32模块,任何型号都可以,因为这个项目所需的资源不是太多,当然了,太老太旧的型号也是不行的。
下图是stm32f103c8t6

有单片机也要有电源是吧,这里使用了一个12V的电源,因为它比较方便

有电源也要有处理电源的东西,一般我们使用AMS1117芯片去降压,也用LDO电路和DC-DC电路去升降压,不过有现成的模块会方便一点。以上仅限于直流电,交流电需要变压器,很大的那种或者其他奇奇怪怪的电路。

这里使用了一个7针的OLED,它可以使用I2C和SPI通信协议进行通信。比较方便、便宜。主要是用来显示灯的挡位的,没有的话也可以,通过观察LED的亮度就可以。

一个直插式小LED,电压大概是3V左右,电流18mA跟单片机的电流差很多,不过不并联电阻也是可以的,就算炸了也没事,一块钱一大堆,炸了也是给自己的教训。一般的LED不会爆炸,只会融化损毁,除非你的LED与众不同。

准备好上面这些东西就可以做了。

是不是还不错,虽然有点丑,不过没关系,能用就行,主要这是我拆了我的小风扇做的。

三、代码

代码一,主函数代码

static u8 title2[5][32] = {
{0x08,0x00,0x29,0x00,0xCA,0x00,0x4C,0xFF,0x78,0x92,0x4C,0x92,0x4A,0x92,0x08,0x92,0x00,0x92,0x7E,0x92,0x42,0x92,0x42,0xFF,0x42,0x00,0x7E,0x00,0x00,0x00,0x00,0x00},/*"智",4*/
{0x10,0x00,0x33,0xFF,0x52,0x48,0x92,0x48,0x12,0x4A,0x52,0x49,0x33,0xFE,0x18,0x00,0x00,0x00,0xFE,0x7E,0x11,0x11,0x11,0x11,0x21,0x21,0x41,0x41,0x07,0x07,0x00,0x00},/*"能",5*/
{0x00,0x10,0x00,0x20,0x00,0xC0,0x07,0x00,0x00,0x00,0x00,0x02,0x00,0x01,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x02,0x00,0x01,0x80,0x00,0x70,0x00,0x00},/*"小",6*/
{0x00,0x00,0x02,0x00,0x07,0x00,0x0A,0x7F,0x12,0x42,0x22,0x42,0xC2,0x42,0x02,0x42,0x02,0x42,0x02,0x42,0x12,0x42,0x0A,0x7F,0x06,0x00,0x03,0x00,0x00,0x00,0x00,0x00},/*"台",7*/
{0x01,0x01,0x0E,0x06,0x00,0x18,0xFF,0xE0,0x04,0x10,0x08,0x0C,0x20,0x00,0x20,0x00,0x20,0x02,0x20,0x01,0x3F,0xFE,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x00,0x00},/*"灯",8*/
};int main(void)
{  InitSoftware();   //初始化软件相关函数InitHardware();   //初始化硬件相关函数printf("Init System has been finished.\r\n" );  //打印系统状态OLEDShowChinese(4,16,Hzk,2,16,0);OLEDShowChinese(28,0,title2,5,16,1);while(1){  CalcPWM(); }
}

是不是非常简单?除了一个OLED的取模。
CalcPWM是用来控制PWM的,以此来控制LED的亮度。这里我使用了一个函数来进行实现。
OLED取模是需要配合自己的OLED代码的,我这里使用了顺向逐列式,当然了,也可以使用其他取模方法。自定义格式一定要使用c51除非有特殊说明。最好是使用十六进制,因为十六进制更加符合OLED屏幕的排列方式。
更多的OLED知识需要自行寻找。
一般我们使用PCtoLCD去取模,不过也可以使用其他软件,在百度上搜一个也可以。(我会上传)

代码二、按键
  因为我使用的是矩阵按键,且较为便宜,因此,不太好用,不过使用开发板的话是可以避免的,可以加一个上拉或下拉电阻,再加一个电容滤波,最后得到的按键信号是较为稳定的。
  这里使用44的矩阵按键,就是4行4列等于16按键,是不是十分巧妙。因此只需要8根线就可以控制16个按键了。
代码如下:

#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "SysTick.h"
#include "LED.h"
#include "KEY.h"int key_val = -1;void InitKeyBoard(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;GPIO_Init(GPIOB,&GPIO_InitStructure);
}	*/
u16 keyboard_scan(void)
{u8 temp = 0;GPIO_ResetBits(GPIOB,GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11);			//拉低行线DelayNms(10);temp=(GPIO_ReadInputData(GPIOB) >> 8)&0xff;	//没有按键按下时扫描if (temp == 0xf0) {DelayNms(50); GPIO_ResetBits(GPIOB,GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11);			//拉低行线DelayNus(10);temp=(GPIO_ReadInputData(GPIOB) >> 8)&0xff;	if (temp != 0xf0) //按键按下时,对键值进行赋值{//第一行GPIO_Write(GPIOB,0);DelayNms(5);GPIO_Write(GPIOB,(uint16_t)(0xFE << 8)); if(((GPIO_ReadInputData(GPIOB) >> 8) & 0XF0) != 0XF0){DelayNms(20);//消抖if(((GPIO_ReadInputData(GPIOB) >> 8) & 0XF0) != 0XF0){temp=((GPIO_ReadInputData(GPIOB) >> 8) & 0XFE);		//对列进行扫描switch(temp){case 0xEE:  key_val = 1;   break;case 0xDE:  key_val = 2;   break;case 0xBE:  key_val = 3;   break;case 0x7E:  key_val = 4;   break;default:    key_val = -1;   break;}}}//第二行GPIO_Write(GPIOB,0);DelayNms(5);GPIO_Write(GPIOB,(uint16_t)(0xFD << 8));if(((GPIO_ReadInputData(GPIOB) >> 8) & 0XF0)!= 0XF0){DelayNms(20);if(((GPIO_ReadInputData(GPIOB) >> 8) & 0XF0) != 0XF0){temp=((GPIO_ReadInputData(GPIOB) >> 8) & 0XFD);switch(temp){case 0xED:  key_val = 5;   break;case 0xDD:  key_val = 6;   break;case 0xBD:  key_val = 7;   break;case 0x7D:  key_val = 8;   break;default:    key_val = -1;   break;}}}//第三行GPIO_Write(GPIOB,0);DelayNms(5);GPIO_Write(GPIOB,(uint16_t)(0xFB << 8));if(((GPIO_ReadInputData(GPIOB) >> 8) & 0XF0) != 0XF0){DelayNms(20);if(((GPIO_ReadInputData(GPIOB) >> 8) & 0XF0) != 0XF0){temp=((GPIO_ReadInputData(GPIOB) >> 8) & 0XFB);switch(temp){case 0xEB:  key_val = 9;   break;case 0xDB:  key_val = 10;   break;case 0xBB:  key_val = 11;   break;case 0x7B:  key_val = 12;   break;default:    key_val = -1;   break;}}}//第四行GPIO_Write(GPIOB,0);DelayNms(5);GPIO_Write(GPIOB,(uint16_t)(0xF7 << 8));if(((GPIO_ReadInputData(GPIOB) >> 8) & 0XF0) !=0XF0){DelayNms(20);if(((GPIO_ReadInputData(GPIOB) >> 8) & 0XF0) != 0XF0){temp=((GPIO_ReadInputData(GPIOB) >> 8) & 0XF7);switch(temp){case 0xE7:  key_val = 13;   break;case 0xD7:  key_val = 14;   break;case 0xB7:  key_val = 15;   break;case 0x77:  key_val = 16;   break;default:    key_val = -1;   break;}}}}}return key_val;}

这个代码可以自己琢磨一下,还是非常巧妙的。
代码三

/*********************************************************************************************************
* 模块名称:OLED.c   
* 摘    要:OLED显示屏模块,4线串行接口,CS、DC、SCK、DIN、RES
* 当前版本:1.0.0
* 作    者:SZLY(COPYRIGHT 2018 - 2020 SZLY. All rights reserved.)
* 完成日期:2020年01月01日
* 内    容:
* 注    意:OLED的显存存放格式如下.[0]0 1 2 3 ... 127[1]0 1 2 3 ... 127[2]0 1 2 3 ... 127[3]0 1 2 3 ... 127[4]0 1 2 3 ... 127[5]0 1 2 3 ... 127[6]0 1 2 3 ... 127[7]0 1 2 3 ... 127                                                                   
**********************************************************************************************************
* 取代版本:
* 作    者:
* 完成日期: 
* 修改内容:
* 修改文件: 
*********************************************************************************************************//*********************************************************************************************************
*                                              包含头文件
*********************************************************************************************************/
#include "OLED.h"
#include "stm32f10x_conf.h"
#include "OLEDFont.h"
#include "SysTick.h"
#include "DelayNms.h"
/*********************************************************************************************************
*                                              宏定义
*********************************************************************************************************/  		   
#define OLED_CMD    0 //命令
#define OLED_DATA   1 //数据//OLED端口定义  
#define CLR_OLED_CS()   GPIO_ResetBits(GPIOA, GPIO_Pin_4)  //CS,片选
#define SET_OLED_CS()   GPIO_SetBits  (GPIOA, GPIO_Pin_4)#define CLR_OLED_RES()  GPIO_ResetBits(GPIOA, GPIO_Pin_6)  //RES,复位
#define SET_OLED_RES()  GPIO_SetBits  (GPIOA, GPIO_Pin_6)#define CLR_OLED_DC()   GPIO_ResetBits(GPIOB, GPIO_Pin_11)   //DC,命令数据标志(0-命令/1-数据)
#define SET_OLED_DC()   GPIO_SetBits  (GPIOB, GPIO_Pin_11)#define CLR_OLED_SCK() GPIO_ResetBits(GPIOA, GPIO_Pin_5)   //SCK,时钟
#define SET_OLED_SCK() GPIO_SetBits  (GPIOA, GPIO_Pin_5)#define CLR_OLED_DIN() GPIO_ResetBits(GPIOA, GPIO_Pin_7)   //DIN,数据
#define SET_OLED_DIN() GPIO_SetBits  (GPIOA, GPIO_Pin_7)/*********************************************************************************************************
*                                              枚举结构体定义
*********************************************************************************************************/	 /*********************************************************************************************************
*                                              内部变量
*********************************************************************************************************/
static  u8  s_arrOLEDGRAM[132][8];    //OLED显存缓冲区/*********************************************************************************************************
*                                              内部函数声明
*********************************************************************************************************/ 
static  void  ConfigOLEDGPIO(void);             //配置OLED的GPIO
static  void  ConfigOLEDReg(void);              //配置OLED的SSD1306寄存器static  u32   CalcPow(u8 m, u8 n);              //计算m的n次方/*********************************************************************************************************
*                                              内部函数实现
*********************************************************************************************************/
/*********************************************************************************************************
* 函数名称:ConfigOLEDGPIO 
* 函数功能:配置OLED的GPIO 
* 输入参数:void 
* 输出参数:void
* 返 回 值:void 
* 创建日期:2018年01月01日
* 注    意:PB12(OLED_CS)、PB14(OLED_RES)、PB11(OLED_DC)、PB13(OLED_SCK)、PB15(OLED_DIN)
*********************************************************************************************************/
static  void  ConfigOLEDGPIO(void)
{GPIO_InitTypeDef  GPIO_InitStructure;//使能RCC相关时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOB的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //使能GPIOC的时钟//配置PB13(OLED_SCK)GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_5;          //设置引脚GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;     //设置模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //设置I/O输出速度GPIO_Init(GPIOA, &GPIO_InitStructure);                //根据参数初始化GPIOGPIO_SetBits(GPIOA, GPIO_Pin_5);                     //设置初始状态为高电平//配置PB15(OLED_DIN)GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_7;          //设置引脚GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;     //设置模式  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //设置I/O输出速度GPIO_Init(GPIOA, &GPIO_InitStructure);                //根据参数初始化GPIOGPIO_SetBits(GPIOA, GPIO_Pin_7);                     //设置初始状态为高电平//配置PB14(OLED_RES)GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6;          //设置引脚GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;     //设置模式  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //设置I/O输出速度GPIO_Init(GPIOA, &GPIO_InitStructure);                //根据参数初始化GPIOGPIO_SetBits(GPIOA, GPIO_Pin_6);                     //设置初始状态为高电平//配置PB12(OLED_CS)GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_4;          //设置引脚GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;     //设置模式  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //设置I/O输出速度GPIO_Init(GPIOA, &GPIO_InitStructure);                //根据参数初始化GPIOGPIO_SetBits(GPIOA, GPIO_Pin_4);                     //设置初始状态为高电平//配置PC3(OLED_DC)GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_11;           //设置引脚GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;     //设置模式  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //设置I/O输出速度GPIO_Init(GPIOB, &GPIO_InitStructure);                //根据参数初始化GPIOGPIO_SetBits(GPIOB, GPIO_Pin_11);                      //设置初始状态为高电平//配置VccGPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0;           //设置引脚GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;     //设置模式  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //设置I/O输出速度GPIO_Init(GPIOB, &GPIO_InitStructure);                //根据参数初始化GPIOGPIO_SetBits(GPIOB, GPIO_Pin_0);                      //设置初始状态为高电平//配置GndGPIO_InitStructure.GPIO_Pin   = GPIO_Pin_1;           //设置引脚GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;     //设置模式  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //设置I/O输出速度GPIO_Init(GPIOB, &GPIO_InitStructure);                //根据参数初始化GPIOGPIO_ResetBits(GPIOB, GPIO_Pin_1);                      //设置初始状态为高电平
}/*********************************************************************************************************
* 函数名称:ConfigOLEDReg 
* 函数功能:配置OLED的寄存器 
* 输入参数:void 
* 输出参数:void
* 返 回 值:void 
* 创建日期:2018年01月01日
* 注    意:
*********************************************************************************************************/
static  void  ConfigOLEDReg( void )
{OLEDWriteByte(0xAE, OLED_CMD); //关闭显示OLEDWriteByte(0xD5, OLED_CMD); //设置时钟分频因子,振荡频率OLEDWriteByte(0x50, OLED_CMD); //[3:0]为分频因子,[7:4]为振荡频率OLEDWriteByte(0xA8, OLED_CMD); //设置驱动路数OLEDWriteByte(0x3F, OLED_CMD); //默认0x3F(1/64) OLEDWriteByte(0xD3, OLED_CMD); //设置显示偏移OLEDWriteByte(0x00, OLED_CMD); //默认为0OLEDWriteByte(0x40, OLED_CMD); //设置显示开始行,[5:0]为行数OLEDWriteByte(0x8D, OLED_CMD); //设置电荷泵OLEDWriteByte(0x14, OLED_CMD); //bit2用于设置开启(1)/关闭(0)OLEDWriteByte(0x20, OLED_CMD); //设置内存地址模式OLEDWriteByte(0x02, OLED_CMD); //[1:0],00-列地址模式,01-行地址模式,10-页地址模式(默认值)OLEDWriteByte(0xA1, OLED_CMD); //设置段重定义,bit0为0,列地址0->SEG0,bit0为1,列地址0->SEG127OLEDWriteByte(0xC0, OLED_CMD); //设置COM扫描方向,bit3为0,普通模式,bit3为1,重定义模式OLEDWriteByte(0xDA, OLED_CMD); //设置COM硬件引脚配置OLEDWriteByte(0x12, OLED_CMD); //[5:4]为硬件引脚配置信息OLEDWriteByte(0x81, OLED_CMD); //设置对比度OLEDWriteByte(0xEF, OLED_CMD); //1~255,默认为0x7F(亮度设置,越大越亮)OLEDWriteByte(0xD9, OLED_CMD); //设置预充电周期OLEDWriteByte(0xf1, OLED_CMD); //[3:0]为PHASE1,[7:4]为PHASE2OLEDWriteByte(0xDB, OLED_CMD); //设置VCOMH电压倍率OLEDWriteByte(0x00, OLED_CMD); //[6:4],000-0.65*vcc,001-0.77*vcc,011-0.83*vccOLEDWriteByte(0xA4, OLED_CMD); //全局显示开启,bit0为1,开启,bit0为0,关闭OLEDWriteByte(0xA6, OLED_CMD); //设置显示方式,bit0为1,反相显示,bit0为0,正常显示 OLEDWriteByte(0xAF, OLED_CMD); //开启显示}/*********************************************************************************************************
* 函数名称:CalcPow
* 函数功能:计算m的n次方
* 输入参数:m,n 
* 输出参数:void
* 返 回 值:m的n次方结果 
* 创建日期:2018年01月01日
* 注    意:
*********************************************************************************************************/
static  u32 CalcPow(u8 m, u8 n)
{u32 result = 1;     //定义用来存放结果的变量      while(n--)          //随着每次循环,n递减,直至为0{                   result *= m;      //循环n次,相当于n个m相乘}                   return result;      //返回m的n次幂的值
}/*********************************************************************************************************
*                                              API函数实现
*********************************************************************************************************/	
/*********************************************************************************************************
* 函数名称:InitOLED
* 函数功能:初始化OLED模块
* 输入参数:void 
* 输出参数:void
* 返 回 值:void 
* 创建日期:2018年01月01日
* 注    意:
*********************************************************************************************************/   
void  InitOLED(void)
{ ConfigOLEDGPIO();     //配置OLED的GPIOCLR_OLED_RES();DelayNms(10);  SET_OLED_RES();       //RES引脚务必拉高DelayNms(10);ConfigOLEDReg();      //配置OLED的寄存器OLEDClear();          //清除OLED屏内容OLEDRefreshGRAM();
}  /*********************************************************************************************************
* 函数名称:OLEDDisplayOn
* 函数功能:开启OLED显示
* 输入参数:void
* 输出参数:void
* 返 回 值:void
* 创建日期:2018年01月01日
* 注    意:
*********************************************************************************************************/   
void  OLEDDisplayOn( void )
{//打开关闭电荷泵,第一个字节为命令字,0x8D,第二个字节设置值,0x10-关闭电荷泵,0x14-打开电荷泵OLEDWriteByte(0x8D, OLED_CMD);  //第一个字节0x8D为命令OLEDWriteByte(0x14, OLED_CMD);  //0x14-打开电荷泵//设置显示开关,0xAE-关闭显示,0xAF-开启显示OLEDWriteByte(0xAF, OLED_CMD);  //开启显示
}/*********************************************************************************************************
* 函数名称:OLEDDisplayOff
* 函数功能:关闭OLED显示
* 输入参数:void
* 输出参数:void
* 返 回 值:void
* 创建日期:2018-01-01
* 注    意:
*********************************************************************************************************/ 
void  OLEDDisplayOff( void )
{//打开关闭电荷泵,第一个字节为命令字,0x8D,第二个字节设置值,0x10-关闭电荷泵,0x14-打开电荷泵OLEDWriteByte(0x8D, OLED_CMD);  //第一个字节为命令字,0x8DOLEDWriteByte(0x10, OLED_CMD);  //0x10-关闭电荷泵//设置显示开关,0xAE-关闭显示,0xAF-开启显示OLEDWriteByte(0xAE, OLED_CMD);  //关闭显示
}/*********************************************************************************************************
* 函数名称:OLEDRefreshGRAM
* 函数功能:将STM32的GRAM写入到SSD1306的GRAM 
* 输入参数:void 
* 输出参数:void
* 返 回 值:void
* 创建日期:2018年01月01日
* 注    意:
*********************************************************************************************************/
void  OLEDRefreshGRAM(void)
{u8 i;u8 n;for(i = 0; i < 8; i++)                  //遍历每一页{                                       OLEDWriteByte(0xb0 + i, OLED_CMD);    //设置页地址(0~7)OLEDWriteByte(0x00, OLED_CMD);        //设置显示位置—列低地址OLEDWriteByte(0x10, OLED_CMD);        //设置显示位置—列高地址 for(n = 0; n < 132; n++)              //遍历每一列{//通过循环将STM32的GRAM写入到SSD1306的GRAMOLEDWriteByte(s_arrOLEDGRAM[n][i], OLED_DATA); }}   
}/*********************************************************************************************************
* 函数名称:OLEDClear
* 函数功能:清屏函数,清完屏整个屏幕是黑色的,和没点亮一样
* 输入参数:void
* 输出参数:void
* 返 回 值:void
* 创建日期:2018年01月01日
* 注    意:
*********************************************************************************************************/  
void  OLEDClear(void)  
{  u8 i;u8 n;for(i = 0; i < 8; i++)          //遍历每一页{                               for(n = 0; n < 132; n++)      //遍历每一列{                             s_arrOLEDGRAM[n][i] = 0x00;   //将指定点清零}                             }                               
}/*********************************************************************************************************
* 函数名称:OLEDWriteByte
* 函数功能:向SSD1306写入一个字节
* 输入参数:dat为要写入的数据或命令,cmd为数据/命令标志,0-命令,1-数据
* 输出参数:void
* 返 回 值:void
* 创建日期:2018年01月01日
* 注    意:
*********************************************************************************************************/
void  OLEDWriteByte(u8 dat, u8 cmd)
{i16 i;//判断要写入数据还是写入命令    if(OLED_CMD == cmd)         //如果标志cmd为传入命令时{                             CLR_OLED_DC();            //DC输出低电平用来读写命令  }                             else if(OLED_DATA == cmd)   //如果标志cmd为传入数据时{                             SET_OLED_DC();            //DC输出高电平用来读写数据  }                             CLR_OLED_CS();              //CS输出低电平为写入数据或命令作准备for(i = 0; i < 8; i++)      //循环8次,从高到低取出要写入的数据或命令的8个bit{                             CLR_OLED_SCK();           //SCK输出低电平为写入数据作准备if(dat & 0x80)            //判断要写入的数据或命令的最高位是1还是0{                           SET_OLED_DIN();         //要写入的数据或命令的最高位是1,DIN输出高电平表示1}                           else                        {                           CLR_OLED_DIN();         //要写入的数据或命令的最高位是0,DIN输出低电平表示0}                           SET_OLED_SCK();           //SCK输出高电平,DIN的状态不再变化,此时写入数据线的数据dat <<= 1;                //左移一位,次高位移到最高位}                             SET_OLED_CS();              //OLED的CS输出高电平,不再写入数据或命令  SET_OLED_DC();              //OLED的DC输出高电平
} /*********************************************************************************************************
* 函数名称:OLEDDrawPoint
* 函数功能:在指定位置画点
* 输入参数:x取值范围为0~127,y取值范围为0~63,t为1表示填充,t为0表示清空
* 输出参数:void
* 返 回 值:void
* 创建日期:2018年01月01日
* 注    意:(1)x-y轴体系的原点坐标在屏幕左上角;
*           (2)物理显示的y与SSD1306显存的COMn的n相加为63,当然,屏幕的行号(按字节)与SSD1306的行号(按
*                字节)相加为7。
*********************************************************************************************************/			   
void  OLEDDrawPoint(u8 x, u8 y, u8 t)
{u8 pos;                           //存放点所在的页数u8 bx;                            //存放点所在的屏幕的行号u8 temp = 0;                      //用来存放画点位置相对于字节的位if(x > 127 || y > 63)             //如果指定位置超过额定范围{                                 return;                         //返回空,函数结束}                                 pos = 7 - y / 8;                  //求指定位置所在页数bx = y % 8;                       //求指定位置在上面求出页数中的行号temp = 1 << (7 - bx);             //(7-bx)求出相应SSD1306的行号,并在字节中相应的位置为1if(t)                             //判断填充标志为1还是0{                                 s_arrOLEDGRAM[x][pos] |= temp;  //如果填充标志为1,指定点填充}                                 else                              {                                 s_arrOLEDGRAM[x][pos] &= ~temp; //如果填充标志为0,指定点清空  }
}/*********************************************************************************************************
* 函数名称:OLEDShowChar
* 函数功能:在指定位置显示一个字符
* 输入参数:x取值范围为0~127,y取值范围为0~63,chr为待显示的字符,size用于选择字体(16/12),mode为取模方式
*           mode为0反白显示,mode为1正常显示
* 输出参数:void
* 返 回 值:void
* 创建日期:2018年01月01日
* 注    意:有6种取模方式
*********************************************************************************************************/
void  OLEDShowChar(u8 x, u8 y, u8 chr, u8 size, u8 mode)
{ u8  temp;                         //用来存放字符顺向逐列式的相对位置u8  t1;                           //循环计数器1u8  t2;                           //循环计数器2u8  y0 = y;                       //当前操作的行数chr = chr - ' ';                  //得到相对于空格(ASCII为0x20)的偏移值,求出要chr在数组中的索引for(t1 = 0; t1 < size; t1++)      //循环逐列显示{                                   if(size == 12)                  //判断字号大小,选择相对的顺向逐列式{                                 temp = g_iASCII1206[chr][t1]; //取出字符在g_iASCII1206数组中的第t1列}                                 else                              {                                 temp = g_iASCII1608[chr][t1]; //取出字符在g_iASCII1608数组中的第t1列                   }                                 for(t2 = 0; t2 < 8; t2++)       //在一个字符的第t2列的横向范围(8个像素)内显示点{                                 if(temp & 0x80)               //取出temp的最高位,并判断为0还是1{                             OLEDDrawPoint(x, y, mode);  //如果temp的最高位为1填充指定位置的点}                               else                            {                               OLEDDrawPoint(x, y, !mode); //如果temp的最高位为0清除指定位置的点}                               temp <<= 1;                   //左移一位,次高位移到最高位y++;                          //进入下一行if((y - y0) == size)          //如果显示完一列{                               y = y0;                     //行号回到原来的位置x++;                        //进入下一列break;                      //跳出上面带#的循环}} } 
}/*********************************************************************************************************
* 函数名称:OLEDShowNum
* 函数功能:显示数字
* 输入参数:x-y为起点坐标,len为数字的位数,size为字体大小,mode为模式(0-填充模式,1-叠加模式)
* 输出参数:void
* 返 回 值:void
* 创建日期:2018年01月01日
* 注    意:num:数值(0~4294967295)
*********************************************************************************************************/	 		  
void  OLEDShowNum(u8 x, u8 y, u32 num, u8 len, u8 size)
{u8 t;                                                       //循环计数器u8 temp;                                                    //用来存放要显示数字的各个位u8 enshow = 0;                                              //区分0是否为高位0标志位for(t = 0; t < len; t++)                                      {                                                             temp = (num / CalcPow(10, len - t - 1) ) % 10;            //按从高到低取出要显示数字的各个位,存到temp中if(enshow == 0 && t < (len - 1))                          //如果标记enshow为0并且还未取到最后一位{                                                           if(temp == 0 )                                          //如果temp等于0{                                                         OLEDShowChar(x + (size / 2) * t, y, '0', size, 1);    //此时的0在高位,用空格替代continue;                                             //提前结束本次循环,进入下一次循环}                                                         else                                                      {                                                         enshow = 1;                                           //否则将标记enshow置为1}                                                                                                                        }                                                           OLEDShowChar(x + (size / 2) * t, y, temp + '0', size, 1); //在指定位置显示得到的数字}
}/*********************************************************************************************************
* 函数名称:OLEDShowString
* 函数功能:显示字符串
* 输入参数:x-y为起点坐标,p为字符串起始地址
* 输出参数:void
* 返 回 值:void
* 创建日期:2018年01月01日
* 注    意:用16号字体显示
*********************************************************************************************************/
void  OLEDShowString(u8 x, u8 y, const u8* p)
{
#define MAX_CHAR_POSX 122             //OLED屏幕横向的最大范围
#define MAX_CHAR_POSY 58              //OLED屏幕纵向的最大范围while(*p != '\0')                   //指针不等于结束符时,循环进入{                                   if(x > MAX_CHAR_POSX)             //如果x超出指定最大范围,x赋值为0{                                 x  = 0;                         y += 16;                        //显示到下一行左端}                                 if(y > MAX_CHAR_POSY)             //如果y超出指定最大范围,x和y均赋值为0{                                 y = x = 0;                      //清除OLED屏幕内容OLEDClear();                    //显示到OLED屏幕左上角OLEDRefreshGRAM();}                                 OLEDShowChar(x, y, *p, 16, 1);    //指定位置显示一个字符x += 8;                           //一个字符横向占8个像素点p++;                              //指针指向下一个字符}  
}/*********************************************************************************************************
* 函数名称:OLEDShowChinese
* 函数功能:显示汉字
* 输入参数:x-y为起点坐标,p为字符串起始地址
* 输出参数:void
* 返 回 值:void
* 创建日期:2018年01月01日
* 注    意:用16号字体显示
*********************************************************************************************************/
void OLEDShowChinese(u8 x,u8 y,u8 chinese[][32],u8 chr,u8 size,u8 mode)
{u8 temp;      //用来存放字符顺向逐列式的相对位置u8 t1;        //循环计数器1u8 t2;        //循环计数器2u8 t3;u8 y0=y;      //当前操作的行数for(t3=0;t3<chr;t3++){for(t1=0;t1<size*2;t1++)            //循行逐列显示{temp=chinese[t3][t1];for(t2=0;t2<8;t2++)             //在一个字符的第t2列的横向范围(8像素)内显示点{if(temp&0x80)                 //取出temp的最高位,并判断是0还是1{OLEDDrawPoint(x,y,mode);    //如果temp最高位是1,填充指定位置的点}else{ OLEDDrawPoint(x,y,!mode);   //如果temp最高位是0,清除指定位置的点}temp<<=1;                     //左移一位,次高位移到最高位y++;                          //进入下一行if((y-y0)==size)              //如果显示完一列{y=y0;                       //行号回到原来的位置x++;                        //进入下一列break;                      //跳出循环}}}}//OLEDRefreshGRAM();
}/*********************************************************************************************************
* 函数名称:OLEDShowPicture
* 函数功能:显示32*32图片
* 输入参数:x-y为起点坐标,
* 输出参数:void
* 返 回 值:void
* 创建日期:2018年01月01日
* 注    意:用16号字体显示
*********************************************************************************************************/
void  OLEDShowPicture(u8 x,u8 y,u8 picture[],u8 mode)
{u8 i=0;u8 t1;u8 t2;u8 t3;u8 temp;for(t1=x ;t1<x+32; t1++){for(t2=0 ;t2<4 ;t2++){temp = picture[i];for(t3=0 ;t3<8 ;t3++){if(temp&0x80)                 //取出temp的最高位,并判断是0还是1{OLEDDrawPoint(t1,y+t2*8+t3,mode);    //如果temp最高位是1,填充指定位置的点}else{ OLEDDrawPoint(t1,y+t2*8+t3,!mode);   //如果temp最高位是0,清除指定位置的点}temp<<=1;                     //左移一位,次高位移到最高位}i++;}}
}

OLED这里没啥好说的,都是固定的东西,改一改就适配了,只适配SPI通信的OLED
代码四、

/*********************************************************************************************************
* 模块名称:CalcPWM.c
* 摘    要:CalcPWM模块
* 当前版本:1.0.0
* 作    者:SZLY(COPYRIGHT 2018 - 2020 SZLY. All rights reserved.)
* 完成日期:2020年01月01日 
* 内    容:
* 注    意:                                                                  
**********************************************************************************************************
* 取代版本:
* 作    者:
* 完成日期:
* 修改内容:
* 修改文件:
*********************************************************************************************************//*********************************************************************************************************
*                                              包含头文件
*********************************************************************************************************/
#include "LED.h"
#include "stm32f10x_conf.h"
#include "PWM.h"
#include "KEY.h"
#include "ADC.h"
#include "OLED.h"
#include "rang.h"
#include "SysTick.h"
#include "bsp_i2c.h"
/*********************************************************************************************************
*                                              宏定义
*********************************************************************************************************//*********************************************************************************************************
*                                              枚举结构体定义
*********************************************************************************************************//*********************************************************************************************************
*                                              内部变量
*********************************************************************************************************/
extern  uint16_t key_val;
static u8 num;
static u8 num2;
static u8 key = 0;static u8 number[7][32] = {{0x08,0x20,0x30,0x20,0xA0,0x40,0xAA,0x50,0xAA,0x90,0xAA,0x94,0xA1,0x54,0xFE,0x32,0xA1,0x12,0xAA,0x95,0xAA,0x98,0xAA,0x40,0xA0,0x40,0x28,0x20,0x30,0x20,0x00,0x00},/*"零",0*/
{0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00},/*"一",0*/
{0x00,0x08,0x00,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x00,0x08,0x00,0x08,0x00,0x00},/*"二",1*/
{0x00,0x04,0x20,0x04,0x21,0x04,0x21,0x04,0x21,0x04,0x21,0x04,0x21,0x04,0x21,0x04,0x21,0x04,0x21,0x04,0x21,0x04,0x21,0x04,0x21,0x04,0x20,0x04,0x00,0x04,0x00,0x00},/*"三",2*/
{0x00,0x00,0x3F,0xFE,0x20,0x14,0x20,0x24,0x20,0xC4,0x3F,0x04,0x20,0x04,0x20,0x04,0x20,0x04,0x3F,0x84,0x20,0x44,0x20,0x44,0x20,0x44,0x3F,0xFE,0x00,0x00,0x00,0x00},/*"四",3*/
{0x00,0x02,0x40,0x02,0x42,0x02,0x42,0x02,0x42,0x1E,0x43,0xE2,0x7E,0x02,0x42,0x02,0x42,0x02,0x42,0x02,0x42,0x02,0x43,0xFE,0x40,0x02,0x40,0x02,0x00,0x02,0x00,0x00},/*"五",4*/};static u8 mode[6][32] = {{0x00,0x40,0x00,0x40,0x24,0x40,0x24,0x40,0x24,0x40,0x24,0x42,0x24,0x41,0x3F,0xFE,0x44,0x40,0x44,0x40,0x44,0x40,0xC4,0x40,0x44,0x40,0x00,0x40,0x00,0x40,0x00,0x00},/*"手",0*/
{0x02,0x08,0x22,0x3C,0x23,0xC8,0x22,0x08,0x22,0x28,0x22,0x1D,0x02,0x02,0x08,0x0C,0x08,0x70,0xFF,0x80,0x08,0x02,0x08,0x01,0x08,0x02,0x0F,0xFC,0x00,0x00,0x00,0x00},/*"动",1*/
{0x02,0x00,0x42,0x00,0x33,0xFE,0x00,0x04,0x00,0x08,0x41,0x00,0x49,0x3F,0x49,0x22,0x4F,0x22,0x79,0x22,0x49,0x22,0x49,0x22,0x4F,0x3F,0x41,0x00,0x01,0x00,0x00,0x00},/*"语",0*/
{0x02,0x00,0x02,0x00,0x22,0x00,0x22,0xFF,0x2A,0x92,0x26,0x92,0xA2,0x92,0x62,0x92,0x22,0x92,0x26,0x92,0x2A,0x92,0x22,0xFF,0x22,0x00,0x02,0x00,0x02,0x00,0x00,0x00},/*"音",1*/
{0x08,0x20,0x06,0x20,0x40,0x7E,0x31,0x80,0x00,0x02,0x00,0x7E,0x7F,0x42,0x49,0x42,0x49,0x7E,0x49,0x42,0x49,0x7E,0x49,0x42,0x7F,0x42,0x00,0x7E,0x00,0x02,0x00,0x00},/*"温",2*/
{0x08,0x40,0x08,0x42,0x08,0x81,0xFF,0xFE,0x09,0x00,0x04,0x02,0x19,0x02,0x12,0x42,0x14,0x42,0x90,0x42,0x70,0x7E,0x14,0x42,0x12,0x42,0x15,0x42,0x18,0x02,0x00,0x00},/*"控",3*/};// ADC1转换的电压值通过MDA方式传到SRAM
extern __IO uint16_t ADC_ConvertedValue[NOFCHANEL];// 局部变量,用于保存转换计算后的电压值 	 
float ADC_ConvertedValueLocal[NOFCHANEL];  float length; //测量的距离extern uint32_t  H1;  //Humility
extern uint32_t  T1;  //Temperature
/*********************************************************************************************************
*                                              内部函数声明
*********************************************************************************************************/
//static void voiceCheck(void);                //语音控制
static void keyCheck(void);                  //按键控制
static void rangeCheck(void);                //测距控制
static void TemparetureCheck(void);          //温度控制
static void PWMControl(u8 number);           //pwm的控制
/*********************************************************************************************************
*                                              内部函数实现
*********************************************************************************************************/
/*********************************************************************************************************
* 函数名称:voiceCheck
* 函数功能:语音控制 
* 输入参数:void 
* 输出参数:void
* 返 回 值:void
* 创建日期:2018年01月01日
* 注    意:
*********************************************************************************************************/
//static void voiceCheck(void)
//{
//  ADC_ConvertedValueLocal[0] =(float) ADC_ConvertedValue[0]/4096*3.3;
//	ADC_ConvertedValueLocal[1] =(float) ADC_ConvertedValue[1]/4096*3.3;
//  ADC_ConvertedValueLocal[2] =(float) ADC_ConvertedValue[2]/4096*3.3;//  if(ADC_ConvertedValueLocal[0] > 1.6 && ADC_ConvertedValueLocal[1] < 1.6 && ADC_ConvertedValueLocal[2] < 1.6)         /*001  一档*/
//  {
//    key = 1;
//    num  = 1;
//  }
//  else if(ADC_ConvertedValueLocal[0] < 1.6 && ADC_ConvertedValueLocal[1] > 1.6 && ADC_ConvertedValueLocal[2] < 1.6)     /*010  二挡*/
//  {
//    key = 1;
//    num = 2;
//  }
//    else if(ADC_ConvertedValueLocal[0] > 1.6 && ADC_ConvertedValueLocal[1] > 1.6 && ADC_ConvertedValueLocal[2] < 1.6)   /*011  三档*/
//  {
//    key = 1;
//    num = 3;
//  }
//    else if(ADC_ConvertedValueLocal[0] < 1.6 && ADC_ConvertedValueLocal[1] < 1.6 && ADC_ConvertedValueLocal[2] > 1.6)   /*100  四挡*/
//  {
//    key = 1;
//    num = 4;
//  }
//    else if(ADC_ConvertedValueLocal[0] > 1.6 && ADC_ConvertedValueLocal[1] < 1.6 && ADC_ConvertedValueLocal[2] > 1.6)   /*101 五档*/
//  {
//    key = 1;
//    num = 5;
//  }
//    else if(ADC_ConvertedValueLocal[0] > 1.6 && ADC_ConvertedValueLocal[1] > 1.6 && ADC_ConvertedValueLocal[2] > 1.6)   /*111 开风扇*/
//  {
//    key = 1;
//    num = num;
//  }
//    else if(ADC_ConvertedValueLocal[0] < 1.6 && ADC_ConvertedValueLocal[1] < 1.6 && ADC_ConvertedValueLocal[2] < 1.6)    /*000  关风扇*/
//  {
//    key = 0;
//    num = 0;
//    SetPWM(0);
//  }
//}static void keyCheck(void)                  //按键控制
{if(keyboard_scan() == 1)              //按键1,增加档位{key_val = 0;                         //按下后不再受到按键的影响num++;if(num > 5){num = 5;}}else if(keyboard_scan() == 2)          //按键2,减小档位{key_val = 0;num--;if(num < 1){num = 0;}}else if(keyboard_scan() == 3)          //按键3,风扇的开关{static u8 num1;key_val = 0;num1++;if(num1 > 2){num1 = 1;}if(num1 == 1){key = 1;num = num;}else if(num1 == 2){key = 0;num = 0;SetPWM(0);}}else if(keyboard_scan() == 16){key = 0;num = 0;} }static void rangeCheck(void)                //测距控制
{length = HCSR04GetLength(); DelayNms(500);if(length > 60.00){num = 0;}else{num = num;}}
static void TemparetureCheck(void)          //温度控制
{DelayNms(500);if(T1 < 27.0){num = 0;}else if(T1 > 27.0 && T1 < 27.5){num = 1;}else if(T1 >= 27.5 && T1 < 28.0){num = 2;}else if(T1 >= 28.0 && T1 < 28.5){num = 3;}else if(T1 >= 28.5 && T1 < 29.0){num = 4;}else if(T1 >= 29.0 && T1 < 30.0){num = 5;}else if(T1 > 30.0){num = 5;}
}static void PWMControl(u8 numb)           //pwm的控制
{if(key == 1){OLEDShowString(4,0,"   ");OLEDShowString(4,0,"ON");SetPWM(numb * 100);}else{OLEDShowString(4,0,"   ");OLEDShowString(4,0,"OFF");}switch(numb){case 1:OLEDShowChinese(52,17,&number[1],1,16,1);break;case 2:OLEDShowChinese(52,17,&number[2],1,16,1);break;case 3:OLEDShowChinese(52,17,&number[3],1,16,1);break;case 4:OLEDShowChinese(52,17,&number[4],1,16,1);break;case 5:OLEDShowChinese(52,17,&number[5],1,16,1);break;default:OLEDShowChinese(52,17,&number[0],1,16,1);break;}OLEDRefreshGRAM();
}/*********************************************************************************************************
*                                              API函数实现
*********************************************************************************************************/
/*********************************************************************************************************
* 函数名称:CalcPWM
* 函数功能:通过按键,语音模块、温度变化等方法改变输出的PWM模块
* 输入参数:void
* 输出参数:void
* 返 回 值:void
* 创建日期:2018年01月01日
* 注    意:
*********************************************************************************************************/
void CalcPWM(void)
{if(keyboard_scan() == 4){num2++;if(num2 > 1){num2 = 0;}}if(num2 == 0){key_val = 0;keyCheck();OLEDShowChinese(70,17,&mode[0],1,16,1);OLEDShowChinese(86,17,&mode[1],1,16,1);}else if(num2 == 1){key_val = 0;
//      voiceCheck();OLEDShowChinese(70,17,&mode[2],1,16,1);OLEDShowChinese(86,17,&mode[3],1,16,1);}
//    else if(num2 == 2)
//    {
//      key_val = 0;
//      TemparetureCheck(); 
//      OLEDShowChinese(70,17,&mode[4],1,16,1);
//      OLEDShowChinese(86,17,&mode[5],1,16,1);
//    }//  read_AHT20_once();
//   rangeCheck();PWMControl(num);//  OLEDShowString(4,48,"Length:");
//  OLEDShowNum(60,52,(int)length,2,12);
//  OLEDShowChar(74,52,'.',12,1);
//  OLEDShowNum(82,52,(int)(length * 100) % 100,2,12);
//  OLEDShowString(100,48,"cm");}

这里是改变PWM波的控制中心,附加了其他的模块代码,不删了,接其他模块的时候可以使用。

最后一个代码就是PWM的配置了。

/*********************************************************************************************************
* 模块名称:PWM.c
* 摘    要:PWM模块
* 当前版本:1.0.0
* 作    者:SZLY(COPYRIGHT 2018 - 2020 SZLY. All rights reserved.)
* 完成日期:2020年01月01日 
* 内    容:
* 注    意:                                                                  
**********************************************************************************************************
* 取代版本:
* 作    者:
* 完成日期:
* 修改内容:
* 修改文件:
*********************************************************************************************************//*********************************************************************************************************
*                                              包含头文件
*********************************************************************************************************/
#include "PWM.h"
#include "stm32f10x.h"
/*********************************************************************************************************
*                                              宏定义
*********************************************************************************************************//*********************************************************************************************************
*                                              枚举结构体定义
*********************************************************************************************************//*********************************************************************************************************
*                                              内部变量
*********************************************************************************************************/
i16 s_iDutyCycle = 0;                      //用于存放占空比值
/*********************************************************************************************************
*                                              内部函数声明
*********************************************************************************************************/
static void ConfigTimer3ForPWMPB5(u16 arr,u16 psc);                 //配置PWM
/*********************************************************************************************************
*                                              内部函数实现
*********************************************************************************************************/
/*********************************************************************************************************
* 函数名称:ConfigTimer3ForPWMPB5
* 函数功能:配置PWM
* 输入参数:u16 arr,u16 psc
* 输出参数:void
* 返 回 值:void
* 创建日期:2018年01月01日
* 注    意:
*********************************************************************************************************/
static void ConfigTimer3ForPWMPB5(u16 arr,u16 psc)
{GPIO_InitTypeDef GPIO_InitStructure;                       TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;//使能RCC相关时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//注意,GPIOGPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE);                        //TIM3部分重映射TIM3.CH2->PB5//配置PB5,对应TIM3的CH2GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStructure);//配置TIM3TIM_TimeBaseStructure.TIM_Period = arr;TIM_TimeBaseStructure.TIM_Prescaler = psc;TIM_TimeBaseStructure.TIM_ClockDivision = 0;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;                 //设置递增计数模式TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);                              //根据参数初始化TIM3//配置TIM3的CH2为PWM模式,在TIM_CounterMode_Up模式下,TIMx_CNT < TIMx_CCRx时为无效电平(高电平)TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;                           //设置为PWM2模式TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;               //使能比较输出TIM_OCInitStructure.TIM_OCPolarity  = TIM_OCPolarity_Low;                   //设置极性,OC2低电平有效TIM_OC2Init(TIM3,&TIM_OCInitStructure);                                     //根据参数初始化TIM3的CH2TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);                                 //使能TIM3的CH2预装载TIM_Cmd(TIM3,ENABLE);                                                        //使能TIM3
}  
/*********************************************************************************************************
*                                              API函数实现
*********************************************************************************************************/
/*********************************************************************************************************
* 函数名称:InitPWM
* 函数功能:初始化PWM
* 输入参数:void
* 输出参数:void
* 返 回 值:void
* 创建日期:2018年01月01日
* 注    意:
*********************************************************************************************************/
void InitPWM(void)
{ConfigTimer3ForPWMPB5(599,999);                                              //配置TIM3,72000000/(999+1)/(599+1) = 120HzTIM_SetCompare2(TIM3,0);                                                     //设置初始值为0
}
/*********************************************************************************************************
* 函数名称:SetPWM
* 函数功能:设置PWM
* 输入参数:i16 val
* 输出参数:void
* 返 回 值:void
* 创建日期:2018年01月01日
* 注    意:
*********************************************************************************************************/
void SetPWM(i16 val)     //设置PWM
{s_iDutyCycle = val;                                                         //获取占空比的值TIM_SetCompare2(TIM3,s_iDutyCycle);                                         //设置占空比
}
/*********************************************************************************************************
* 函数名称:IncPWMDutyCycle
* 函数功能:增加PWM
* 输入参数:void
* 输出参数:void
* 返 回 值:void
* 创建日期:2018年01月01日
* 注    意:
*********************************************************************************************************/
void IncPWMDutyCycle(void)   //增加PWM
{if(s_iDutyCycle >= 600){s_iDutyCycle = 600;}else{s_iDutyCycle += 100;}TIM_SetCompare2(TIM3,s_iDutyCycle);
}
/*********************************************************************************************************
* 函数名称:DecPWMDutyCycle
* 函数功能:减少PWM
* 输入参数:void
* 输出参数:void
* 返 回 值:void
* 创建日期:2018年01月01日
* 注    意:
*********************************************************************************************************/
void DecPWMDutyCycle(void)   //减少PWM
{if(s_iDutyCycle <= 0){s_iDutyCycle = 0;}else{s_iDutyCycle -= 100;}TIM_SetCompare2(TIM3,s_iDutyCycle);                                               //设置占空比
}

当然了,这里也是标准配置,自己研究研究就会了。前提是知道啥是PWM

四、成品

/?vd_source=de78c9e88a60b2bce782148bbf8657b2

更多推荐

一个小项目

本文发布于:2024-02-12 05:47:17,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1686423.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:项目

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!