项目"/>
一个小项目
基于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
更多推荐
一个小项目
发布评论