STC8H_PWM制作呼吸灯

这篇具有很好参考价值的文章主要介绍了STC8H_PWM制作呼吸灯。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

主要特性

stc8h pwm,电路应用,1024程序员节,嵌入式硬件,硬件工程,单片机
stc8h pwm,电路应用,1024程序员节,嵌入式硬件,硬件工程,单片机

时基单元

stc8h pwm,电路应用,1024程序员节,嵌入式硬件,硬件工程,单片机
stc8h pwm,电路应用,1024程序员节,嵌入式硬件,硬件工程,单片机

16位PWMA_ARR寄存器的写操作

stc8h pwm,电路应用,1024程序员节,嵌入式硬件,硬件工程,单片机

stc8h pwm,电路应用,1024程序员节,嵌入式硬件,硬件工程,单片机

预分频器

stc8h pwm,电路应用,1024程序员节,嵌入式硬件,硬件工程,单片机

PWM模式

stc8h pwm,电路应用,1024程序员节,嵌入式硬件,硬件工程,单片机
stc8h pwm,电路应用,1024程序员节,嵌入式硬件,硬件工程,单片机
PWM边沿对齐模式
stc8h pwm,电路应用,1024程序员节,嵌入式硬件,硬件工程,单片机
寄存器描述
输出使能寄存器(PWMx_ENO)
stc8h pwm,电路应用,1024程序员节,嵌入式硬件,硬件工程,单片机

功能实现说明:
通过定时器递增或递减来设置PWM的占空比调节亮度,最终显示出呼吸灯的效果

代码部分
PWM程序模块

#ifndef _PWM_H_
#define _PWM_H_

#include "GPIO.h"

#define PWM1_CCMR1_ADDR  0xfec8	//CCMR2_ADDR = CCMR1_ADDR + 1
#define PWM1_CCR1_ADDR   0xfed5 //CCR2_ADDR = CCR1_ADDR + 2
#define PWM1_CCER1_ADDR  0xfecc //CCER2_ADDR = CCER1_ADDR + 1

#define PWM2_CCMR1_ADDR  0xfee8 //CCMR2_ADDR = CCMR1_ADDR + 1
#define PWM2_CCR1_ADDR   0xfef5	//CCR2_ADDR = CCR1_ADDR + 2
#define	PWM2_CCER1_ADDR  0xfeec //CCER2_ADDR = CCER1_ADDR + 1

typedef enum
{
	PWM1P_P10 = 0x00, PWM1N_P11,
	PWM1P_P20, PWM1N_P21,
	PWM1P_P60, PWM1N_P61,

	PWM2P_P12 = 0x10, PWM2N_P13,
	PWM2P_P22, PWM2N_P23,
	PWM2P_P62, PWM2N_P63,

	PWM3P_P14 = 0x20, PWM3N_P15,
	PWM3P_P24, PWM3N_P25,
	PWM3P_P64, PWM3N_P65,

	PWM4P_P16 = 0x30, PWM4N_P17,
	PWM4P_P26, PWM4N_P27,
	PWM4P_P66, PWM4N_P67,
	PWM4P_P34, PWM4N_P33,

	PWM5_P20 = 0x40,
	PWM5_P17,
	PWM5_P00,
	PWM5_P74,

	PWM6_P21 = 0x50,
	PWM6_P54,
	PWM6_P01,
	PWM6_P75,

	PWM7_P22 = 0x60,
	PWM7_P33,
	PWM7_P02,
	PWM7_P76,

	PWM8_P23 = 0x70,
	PWM8_P34,
	PWM8_P03,
	PWM8_P77,

}PWM_CH;


//-------------------------------------------------------------------------------------------------------------------
//  @brief      PWM_gpio配置
//  @param      pwmch       PWM通道
//  @return     void
//  Sample usage:           
//-------------------------------------------------------------------------------------------------------------------
void pwm_set_gpio(PWM_CH pwmch)
{
	switch (pwmch)
	{
		case PWM1P_P10:
		{
			pinMode(P10, GPIO_PP);
			break;
		}
		case PWM1N_P11:
		{
			pinMode(P11, GPIO_PP);
			break;
		}
		case PWM1P_P20:
		{
			pinMode(P20, GPIO_PP);
			break;
		}
		case PWM1N_P21:
		{
			pinMode(P21, GPIO_PP);
			break;
		}
		case PWM1P_P60:
		{
			pinMode(P60, GPIO_PP);
			break;
		}
		case PWM1N_P61:
		{
			pinMode(P61, GPIO_PP);
			break;
		}

		case PWM2P_P12:
		{
			pinMode(P12, GPIO_PP);
			break;
		}
		case PWM2N_P13:
		{
			pinMode(P13, GPIO_PP);
			break;
		}
		case PWM2P_P22:
		{
			pinMode(P22, GPIO_PP);
			break;
		}
		case PWM2N_P23:
		{
			pinMode(P23, GPIO_PP);
			break;
		}
		case PWM2P_P62:
		{
			pinMode(P62, GPIO_PP);
			break;
		}
		case PWM2N_P63:
		{
			pinMode(P63, GPIO_PP);
			break;
		}

		case PWM3P_P14:
		{
			pinMode(P14, GPIO_PP);
			break;
		}
		case PWM3N_P15:
		{
			pinMode(P15, GPIO_PP);
			break;
		}
		case PWM3P_P24:
		{
			pinMode(P24, GPIO_PP);
			break;
		}
		case PWM3N_P25:
		{
			pinMode(P25, GPIO_PP);
			break;
		}
		case PWM3P_P64:
		{
			pinMode(P64, GPIO_PP);
			break;
		}
		case PWM3N_P65:
		{
			pinMode(P65, GPIO_PP);
			break;
		}
		case PWM4P_P16:
		{
			pinMode(P16, GPIO_PP);
			break;
		}
		case PWM4N_P17:
		{
			pinMode(P17, GPIO_PP);
			break;
		}
		case PWM4P_P26:
		{
			pinMode(P26, GPIO_PP);
			break;
		}
		case PWM4N_P27:
		{
			pinMode(P27, GPIO_PP);
			break;
		}
		case PWM4P_P66:
		{
			pinMode(P66, GPIO_PP);
			break;
		}
		case PWM4N_P67:
		{
			pinMode(P67, GPIO_PP);
			break;
		}
		case PWM4P_P34:
		{
			pinMode(P34, GPIO_PP);
			break;
		}
		case PWM4N_P33:
		{
			pinMode(P33, GPIO_PP);
			break;
		}


		case PWM5_P20:
		{
			pinMode(P20, GPIO_PP);
			break;
		}
		case PWM5_P17:
		{
			pinMode(P17, GPIO_PP);
			break;
		}
		case PWM5_P00:
		{
			pinMode(P00, GPIO_PP);
			break;
		}
		case PWM5_P74:
		{
			pinMode(P74, GPIO_PP);
			break;
		}
		case PWM6_P21:
		{
			pinMode(P21, GPIO_PP);
			break;
		}
		case PWM6_P54:
		{
			pinMode(P54, GPIO_PP);
			break;
		}
		case PWM6_P01:
		{
			pinMode(P01, GPIO_PP);
			break;
		}
		case PWM6_P75:
		{
			pinMode(P75, GPIO_PP);
			break;
		}
		case PWM7_P22:
		{
			pinMode(P22, GPIO_PP);
			break;
		}
		case PWM7_P33:
		{
			pinMode(P33, GPIO_PP);
			break;
		}
		case PWM7_P02:
		{
			pinMode(P02, GPIO_PP);
			break;
		}
		case PWM7_P76:
		{
			pinMode(P76, GPIO_PP);
			break;
		}
		case PWM8_P23:
		{
			pinMode(P23, GPIO_PP);
			break;
		}
		case PWM8_P34:
		{
			pinMode(P34, GPIO_PP);
			break;
		}
		case PWM8_P03:
		{
			pinMode(P03, GPIO_PP);
			break;
		}
		case PWM8_P77:
		{
			pinMode(P77, GPIO_PP);
			break;
		}
	}
}


//-------------------------------------------------------------------------------------------------------------------
//  @brief      PWM初始化
//  @param      pwmch       PWM通道
//  @param      freq        PWM频率64Hz-3MHz)
//  @param      duty        PWM占空比
//  @return     void
//  Sample usage:           
//							pwm_init(PWM0_P00, 100, 5000);     //通道PWM0  引脚P0.0  频率100  占空比5000
//							PWM_DUTY_MAX为10000
//-------------------------------------------------------------------------------------------------------------------
void pwm_init(PWM_CH pwmch, uint32 freq, uint16 duty)
{

	uint16 match_temp;
	uint16 period_temp;
	uint16 freq_div = 0;

	P_SW2 |= 0x80;

	//GPIO端口配置
	pwm_set_gpio(pwmch);

	freq_div = ((uint32)(sys_clk / freq)) >> 16;				//分频

	period_temp = (sys_clk / freq) / (freq_div + 1) - 1;		//周期时间

	match_temp = period_temp * ((float)duty / PWM_DUTY_MAX);	//占空比

	if (PWM5_P20 <= pwmch)				//PWM5-8
	{

		PWM2_ENO |= (1 << ((2 * ((pwmch >> 4) - 4))));					//使能输出
		PWM2_PS |= ((pwmch & 0x03) << ((2 * ((pwmch >> 4) - 4))));		//输出脚选择

		// 配置通道输出使能和极性	
		(*(unsigned char volatile xdata*)(PWM2_CCER1_ADDR + (((pwmch >> 4) - 4) >> 1))) |= (1 << (((pwmch >> 4) & 0x01) * 4));

		//通道模式配置
		(*(unsigned char volatile xdata*)(PWM2_CCMR1_ADDR + ((pwmch >> 4) - 4))) |= 0x06 << 4;	//
		(*(unsigned char volatile xdata*)(PWM2_CCMR1_ADDR + ((pwmch >> 4) - 4))) |= 1 << 3;		//PWM模式2

		//设置周期时间(高字节先写入)
		//PWM2_ARR = (uint16)period_temp;
		PWM2_ARRH = period_temp >> 8;
		PWM2_ARRL = period_temp;
		//PWM2_ARR=2000;

		//PWM预分频(高字节先写入)
		PWM2_PSCRH = freq_div >> 8;
		PWM2_PSCRL = freq_div;

		//设置占空比(高字节先写入)
		(*(unsigned char volatile xdata*)(PWM2_CCR1_ADDR + 2 * ((pwmch >> 4) - 4))) = match_temp >> 8;
		(*(unsigned char volatile xdata*)(PWM2_CCR1_ADDR + 2 * ((pwmch >> 4) - 4) + 1)) = match_temp;
		
		PWM2_BKR = 0x80; 	//使能主输出
		PWM2_CR1 = 0x01;	//PWM开始计时
	}
	else
	{
		PWM1_ENO |= (1 << (pwmch & 0x01)) << ((pwmch >> 4) * 2);	//使能输出	
		PWM1_PS |= ((pwmch & 0x07) >> 1) << ((pwmch >> 4) * 2);    //输出脚选择


		// 配置通道输出使能和极性
		(*(unsigned char volatile xdata*)(PWM1_CCER1_ADDR + (pwmch >> 5))) |= (1 << ((pwmch & 0x01) * 2 + ((pwmch >> 4) & 0x01) * 0x04));


		(*(unsigned char volatile xdata*)(PWM1_CCMR1_ADDR + (pwmch >> 4))) |= 0x06 << 4;	
		(*(unsigned char volatile xdata*)(PWM1_CCMR1_ADDR + (pwmch >> 4))) |= 1 << 3;		//PWM模式2

		//设置周期时间(高字节先写入)
		//PWM1_ARR = period_temp;
		PWM1_ARRH = period_temp >> 8;
		PWM1_ARRL = period_temp;

		//PWM预分频(高字节先写入)
		PWM1_PSCRH = freq_div >> 8;
		PWM1_PSCRL = freq_div;

		//设置占空比(高字节先写入)
		(*(unsigned char volatile xdata*)(PWM1_CCR1_ADDR + 2 * (pwmch >> 4))) = match_temp >> 8;
		(*(unsigned char volatile xdata*)(PWM1_CCR1_ADDR + 2 * (pwmch >> 4) + 1)) = match_temp;

		PWM1_BKR = 0x80; 	//使能主输出
		PWM1_CR1 = 0x01;	//PWM开始计时
	}

	//P_SW2 &= 0x7F;

}

//-------------------------------------------------------------------------------------------------------------------
//  @brief      PWM调整占空比
//  @param      pwmch       PWM引脚
//  @param      duty        PWM占空比
//  @return     void
//  Sample usage:           pwm_duty(PWM0_P00, 5000);     //通道PWM0  引脚P0.0  占空比5000
//							
//-------------------------------------------------------------------------------------------------------------------
void pwm_duty(PWM_CH pwmch, uint16 duty)
{
	uint16 match_temp;

	//	P_SW2 |= 0x80;
	if (PWM5_P20 <= pwmch)				//PWM5-8
	{
		match_temp = PWM2_ARRH;
		match_temp = match_temp << 8;
		match_temp = match_temp + PWM2_ARRL;
		match_temp = match_temp * ((float)duty / PWM_DUTY_MAX);				//占空比
		(*(unsigned char volatile xdata*)(PWM2_CCR1_ADDR + 2 * ((pwmch >> 4) - 4))) = match_temp >> 8;
		(*(unsigned char volatile xdata*)(PWM2_CCR1_ADDR + 2 * ((pwmch >> 4) - 4) + 1)) = match_temp;
	}
	else
	{
		match_temp = PWM1_ARRH;
		match_temp = match_temp << 8;
		match_temp = match_temp + PWM1_ARRL;
		match_temp = match_temp *((float)duty / PWM_DUTY_MAX);				//占空比
		(*(unsigned char volatile xdata*)(PWM1_CCR1_ADDR + 2 * (pwmch >> 4))) = match_temp >> 8;
		(*(unsigned char volatile xdata*)(PWM1_CCR1_ADDR + 2 * (pwmch >> 4) + 1)) = match_temp;
	}
	//	P_SW2 &= ~0x80;

}

//-------------------------------------------------------------------------------------------------------------------
//  @brief      PWM调整频率和占空比
//  @param      pwmch       PWM通道
//  @param      freq        PWM频率
//  @param      duty        PWM占空比
//  @return     void
//  Sample usage:           pwm_freq(PWM0_P00, 50, 5000);     //通道PWM0  引脚P0.0  频率50  占空比5000
//-------------------------------------------------------------------------------------------------------------------
void pwm_freq_duty(PWM_CH pwmch, uint16 freq, uint16 duty)
{
	uint16 match_temp;
	uint16 period_temp;
	uint16 freq_div = 0;

	freq_div = (sys_clk / freq) >> 15;								//分频
	period_temp = sys_clk / freq / (freq_div + 1);					//频率

	//match_temp = period_temp * duty;
	//match_temp = match_temp / PWM_DUTY_MAX;
	match_temp = period_temp * ((float)duty / PWM_DUTY_MAX);	//占空比

//	P_SW2 |= 0x80;
	if (PWM5_P20 <= pwmch)				//PWM5-8
	{
		//周期(高字节先写入)
		//PWM2_ARR = (uint16)period_temp;
		PWM2_ARRH = period_temp >> 8;
		PWM2_ARRL = period_temp;
		//PWM预分频(高字节先写入)
		PWM2_PSCRH = freq_div>>8;
		PWM2_PSCRL = freq_div;
		//占空比(高字节先写入)
		//(*(unsigned int volatile xdata*)(PWM2_CCR1_ADDR + 2 * ((pwmch >> 4) - 4))) = match_temp;
		(*(unsigned char volatile xdata*)(PWM2_CCR1_ADDR + 2 * ((pwmch >> 4) - 4))) = match_temp >> 8;
		(*(unsigned char volatile xdata*)(PWM2_CCR1_ADDR + 2 * ((pwmch >> 4) - 4) + 1)) = match_temp;
		
	}
	else
	{
		//周期(高字节先写入)
		//PWM2_ARR = (uint16)period_temp;
		PWM1_ARRH = period_temp >> 8;
		PWM1_ARRL = period_temp;
		//PWM预分频(高字节先写入)
		PWM1_PSCR = freq_div;
		//占空比(高字节先写入)
		//(*(unsigned int volatile xdata*)(PWM1_CCR1_ADDR + 2 * (pwmch >> 4))) = match_temp;
		(*(unsigned char volatile xdata*)(PWM1_CCR1_ADDR + 2 * (pwmch >> 4))) = match_temp >> 8;
		(*(unsigned char volatile xdata*)(PWM1_CCR1_ADDR + 2 * (pwmch >> 4) + 1)) = match_temp;
		
	}
	//	P_SW2 &= ~0x80;
}
#endif

主函数部分

	//pwm_LED初始化--------------
	pwm_init(PWM4P_P16, 2000, 800);//pwm初始化三个参数分别是引脚、频率、占空比10/PWM_DUTY_MAX

中断部分文章来源地址https://www.toymoban.com/news/detail-519310.html

//========================================================================
// 描述: 定时器控制呼吸灯计数和ADC与DAC数据对比
// 参数: none.
// 返回: none.
//========================================================================
void T_IRQ0(void) interrupt 12 using 0{

    if(coun_advance == 1){
      counter = counter + 10;
      if(counter == 1000){
        coun_advance = 0;
        coun_retreat = 1;
      }
    }
    else{
      if(coun_retreat == 1){
        counter = counter - 10;
        if(counter == 0){
          coun_retreat = 0;
          coun_advance = 1;
        }
      }
    }
		pwm_duty(PWM4P_P16, counter);//pwm调整三个参数分别是引脚、频率、占空比10/PWM_DUTY_MAX

}

到了这里,关于STC8H_PWM制作呼吸灯的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STC8H系列单片机入门教程之ADC基础知识(四)

    目录 一、A/D转换过程 二、ADC转换流程图 三、采样定理 四、ADC基本参数 4.1、分辨率 4.2、采样速率 4.3、转换时间 4.4、量程  4.5、最低有效位 五、静态参数 5.1、微分非线性 5.2、积分非线性 六、逐次逼近型模数转换器 七、ADC常用分压电路 八、示例代码 ADC即模数转换器,用来

    2024年04月11日
    浏览(59)
  • STC8H系列单片机入门教程之GPIO基本知识(一)

    IO口即输入输出口,STC8H系列单片机支持四种工作模式, 即准双向口、推挽输出、高阻输入、开漏输出,每个IO通过两个寄存器进行配置,如下图所示,注:n = 0,1,2,3,4,5,6,7。 PnM1 PnM0 I/O 口工作模式 0 0 准双向口(弱上拉),灌电流可达 20mA ,拉电流 150-270uA 0 1 推挽输出,强上拉

    2024年04月14日
    浏览(68)
  • STC8H8K64U单片机PWM配置

    STC8H8K64U单片机配置PWM的通道1、通道2、通道7、通道8。STC8可以分为两组PWM,PWMA和PWMB,在使用时,如果同时使用了两组,那么两组的寄存器需要同时配置。 边沿对齐 PWM输出频率 = 系统工作频率 / (PWMx_PSCR + 1) * (PWMx_ARR + 1); 中间对齐 PWM输出频率 = 系统工作频率 / (PWMx_PSCR + 1) *

    2024年02月11日
    浏览(44)
  • 『STC8H8K64U』概述

            大家好,我是初尧.C。希望看完这篇文章对你能有所帮助,不足之处请指正~📝         本文由初尧.C 原创 CSDN首发 如需转载还请通知🚫         📌无端坠入凡生梦. 却惹三千烦恼丝📌         欢迎各位💘点赞+收藏+留言💖         系列专栏― STC8H8K64U🎨     

    2024年02月05日
    浏览(41)
  • STC8h1k28六个基本实验

    实验内容: 项目1: 参考原理图,设计1位闪烁灯程序,每次亮、灭时长均为500ms。 项目2: 参考原理图,设计三色流转灯程序,GRB三种颜色的LED轮番点亮,每次只亮一盏,每次点亮时长为500ms。 原理图: 实验原理: (共阳)LED负极接单片机IO口(P00P01P02),当IO口输出低电

    2024年02月04日
    浏览(50)
  • STC8H8K64U单片机-ADC采集数

    配置单片机的ADC时一定要将IO口配置成高阻输入模式, 以下是单片机引脚对应的ADC通道  

    2024年02月07日
    浏览(42)
  • STC8H8K蓝牙智能巡线小车——3.按键开关状态获取

    电路分析 引脚为P37 开关未按下时,P37是高电平 开关按下时,GND导通,P37是低电平 编程思路 Driver目录中添加KEY.h文件,应包含引脚定义、开关GPIO实例化函数、开关状态获取函数以及当按下和未按下时执行不同的函数(函数指针作为函数参数) Driver目录中添加KEY.c文件,做具

    2024年01月17日
    浏览(49)
  • 8051如何仿真,STC8H8K64U自带硬件USB直接仿真

    8051如何仿真,STC8H8K64U自带硬件USB直接仿真,解决8051的仿真问题,USB直接下载用户程序。 STC8H8K64U 系列单片机不仅可以借助STC专用工具—— STC-USB Link1D 和 一箭双雕之USB转双串口/全自动烧录器 进行串口仿真还可以 直接通过芯片自带的硬件USB接口进行仿真、烧录。下面是用自

    2024年02月09日
    浏览(38)
  • STC8H8K蓝牙智能巡线小车——1. 环境搭建(基于RTX51操作系统)

    开发环境准备:Keil uVision5 烧录软件:STC-ISP(V6.92A) 芯片: STC8H8K64U-45I-LQFP64 芯片引脚: 打开Keil,点击【Project】,选择【new uVersion project】 Device选择【STC MCU Database】 在search中输入“8H8K”,选择【STC8H8K64U Series】,点击【ok】 选择项目所在的文件夹,添加一个Keil项目

    2024年01月17日
    浏览(52)
  • 16个触摸按键,16个8段LED数码管大电流自动刷新,STC8H4K64TL

    16个触摸按键,16个8段LED数码管大电流自动涮新,STC8H4K64TL STC8H4K64TL-45MHz-LQFP48/32, QFN48/32, 主要功能演示板, 附详细的演示程序/原理图,大家可在本贴技术讨论 1,演示了16个触摸按键输入的效果, 2,演示了 大电流自动涮新 16个8段LED数码管,简化了硬件设计,减轻了CPU的压力,

    2024年02月10日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包