STC8H8K64U 学习笔记 - PWM

news2024/11/27 0:48:43

STC8H8K64U 学习笔记 - PWM

  • 环境说明
    • 引脚说明
  • PWM
    • 呼吸灯
    • 震动马达
  • 乐谱

环境说明

该内容仅针对我自己学习的开发板做的笔记,在实际开发中需要针对目标电路板的原理图进行针对性研究。

  • 芯片:STC8H8K64U
  • 烧录软件:stc-isp-v6.92G
  • 编码工具:天问

引脚说明

  • P0_0:蜂鸣器,按频率发音,1:高,0:低
  • P0_1:电动马达,0:停,1:动
  • P5_3:小蓝灯,0:灭,1:亮
  • P2_7:1 号 LED 灯,0:亮,1:灭
  • P2_6:2 号 LED 灯,0:亮,1:灭
  • P1_5:3 号 LED 灯,0:亮,1:灭
  • P1_4:4 号 LED 灯,0:亮,1:灭
  • P2_3:5 号 LED 灯,0:亮,1:灭
  • P2_2:6 号 LED 灯,0:亮,1:灭
  • P2_1:7 号 LED 灯,0:亮,1:灭
  • P2_0:8 号 LED 灯,0:亮,1:灭
  • P5_1:1 号按键,0:按下,1:弹起
  • P5_2:2 号按键,0:按下,1:弹起
  • P5_3:3 号按键,0:按下,1:弹起
  • P5_4:4 号按键,0:按下,1:弹起
  • P3_4:矩阵键盘第 1 行引脚
  • P3_5:矩阵键盘第 2 行引脚
  • P4_0:矩阵键盘第 3 行引脚
  • P4_1:矩阵键盘第 4 行引脚
  • P0_3:矩阵键盘第 1 列引脚
  • P0_6:矩阵键盘第 2 列引脚
  • P0_7:矩阵键盘第 3 列引脚
  • P1_7:矩阵键盘第 4 列引脚

PWM

  • 频率和周期的关系
    • 频率(Frequency): 表示单位时间内发生事件的次数。常用单位是赫兹(Hz),1赫兹等于每秒一个周期。
    • 周期(Period): 表示一个完整事件发生所需的时间。周期是频率的倒数。
    • 举例:
      • 24MHz(兆赫兹),每秒计算24M次,1M = 1k * 1k = 1 000 000
        • 那么周期的时间就是1/24MHz=41.67ns,那么计算1次需要41.67ns,就是说执行1次所需的时间
  • PWM全称是脉宽调制(Pulse Width Modulation),是一种通过改变信号的脉冲宽度来控制电路输出的技术。
  • PWM与引脚对应关系(引脚来源:《stc8h.pdf》的 997 页)

在这里插入图片描述

呼吸灯

通过 PWM 设置 LED 灯的亮度

#define PWM_DUTY_MAX 1000//PWM最大占空比值

#include <STC8HX.h>
uint32 sys_clk = 24000000;//设置PWM、定时器、串口、EEPROM频率参数
#include "lib/twen_board.h"
#include "lib/PWM.h"
#include "lib/delay.h"

uint16 index = 0;
int16 inc = 5;
uint16 frequency = 1000;

void setup() {
  twen_board_init();//天问51初始化
  
  pwm_init(PWM4N_P27, frequency, 0);
  pwm_init(PWM4P_P26, frequency, 0);
  // pwm_init(PWM3N_P15, frequency, 0);
  // pwm_init(PWM3P_P14, frequency, 0);
  // pwm_init(PWM2N_P23, frequency, 0);
  // pwm_init(PWM2P_P22, frequency, 0);
  // pwm_init(PWM1N_P21, frequency, 0);
  // pwm_init(PWM1P_P20, frequency, 0);
}

void loop() {
  pwm_duty(PWM4N_P27, index);
  pwm_duty(PWM4P_P26, index);
  // pwm_duty(PWM3N_P15, index);
  // pwm_duty(PWM3P_P14, index);
  // pwm_duty(PWM2N_P23, index);
  // pwm_duty(PWM2P_P22, index);
  // pwm_duty(PWM1N_P21, index);
  // pwm_duty(PWM1P_P20, index);
  
  delay(1);
  if(index >= 1000) {
    inc = -5;
  }
  if(index <= 0) {
    inc = 5;
  }
  index+= inc;
}

void main(void) {
  setup();
  while(1){
    loop();
  }
}

震动马达

通过 PWM 设置马达的震动强度

#define PWM_DUTY_MAX 1000//PWM最大占空比值

#include <STC8HX.h>
uint32 sys_clk = 24000000;//设置PWM、定时器、串口、EEPROM频率参数
#include "lib/twen_board.h"
#include "lib/PWM.h"
#include "lib/delay.h"

uint16 index = 0;
int16 inc = 5;
uint16 frequency = 1000;

void setup() {
  twen_board_init();//天问51初始化
  
  pwm_init(PWM6_P01, frequency, 0);
  P0M1&=~0x02;P0M0|=0x02;//推挽输出
}

void loop() {  
  pwm_duty(PWM6_P01, index);
  
  delay(1);
  if(index >= 1000) {
    inc = -5;
  }
  if(index <= 0) {
    inc = 5;
  }
  index+= inc;
}

void main(void) {
  setup();
  while(1){
    loop();
  }
}

乐谱

#define PWM_DUTY_MAX 1000//PWM最大占空比值

#include <STC8HX.h>
uint32 sys_clk = 24000000;//设置PWM、定时器、串口、EEPROM频率参数
#include "lib/twen_board.h"
#include "lib/UART.h"
#include "lib/PWM.h"

// 哆Do  来Re  咪Mi  发Fa  唆So  拉La  西Si  哆Do
// 523,  587,  659,  698,  784,  880,  988,  1047
// 1047, 1175, 1319, 1397, 1568, 1760, 1976, 2093
// 2093, 2349, 2637, 2794, 3135, 3520, 3951, 4186

// 设定小字2组的音阶
#define s2_Do 1047
#define s2_Re 1175
#define s2_Mi 1319
#define s2_Fa 1397
#define s2_So 1568
#define s2_La 1760
#define s2_Si 1976
// 设定小字3组的音阶
#define s3_Do 2093
#define s3_Re 2349
#define s3_Mi 2637
#define s3_Fa 2794
#define s3_So 3135
#define s3_La 3520
#define s3_Si 3951
#define s4_Do 4186
// 设定默认的中音(小字2组的音阶)
#define M1 1047
#define M2 1175
#define M3 1319
#define M4 1397
#define M5 1568
#define M6 1760
#define M7 1976
// 设定默认的高音(小字3组的音阶)
#define G1 2093
#define G2 2349
#define G3 2637
#define G4 2794
#define G5 3135
#define G6 3520
#define G7 3951

void putchar(char c) {
  if (c == '\n') {
    uart_putchar(UART_1, 0x0d);
    uart_putchar(UART_1, 0x0a);
  } else {
    uart_putchar(UART_1, (uint8)c);
  }
}

// 每个音阶之间的停顿时间
uint16 spot = 200;
// 单个音阶的持续时间
uint16 duration = 100;
// 按键按下标志位
uint8 pressed1 = 0;
uint8 pressed2 = 0;
// 连续播放乐谱数组过程中的循环索引值
uint16 index = 0;
// 连续播放乐谱数组过程中的循环长度
uint16 lenth = 0;

void setup() {
  twen_board_init();//天问51初始化
  P0M1&=~0x01;P0M0|=0x01;//推挽输出
  uart_init(UART_1, UART1_RX_P30, UART1_TX_P31, 115200, TIM_1);//初始化串口
}

// 启动蜂鸣器(输入单位 hz)
// @param hz        蜂鸣器输入频率
// @param recess    与下一个音阶之间的休息时间
void launchBuzzer(const uint16 hz, uint16 recess) {
  // 假设入参是 523 Hz, 即  523 次/秒
  // 换算为 1000ms 执行 523 次
  // 得到每次执行的时间是 1000ms / 523 次 ≈ 1.912 ms
  // 高低电平各占一半, 即约等于 0.956 ms
  
  // duration = 1000 / hz / 2;
  // printf_small("duration is %d\n", duration);
  // P0_0 = 1;
  // delay(duration);
  // P0_0 = 0;
  // delay(duration);
  
  if(hz == 0) {
    // 如果传入是 0 表示该音阶置空
    delay(duration);
    return;
  }
  pwm_init(PWM5_P00, hz, 500);
  delay(duration);
  pwm_duty(PWM5_P00, 0);
  if(recess > 0) {
    delay(recess);
  }
}

// 乐谱 —— 生日快乐
xdata uint16 music_score_birthday[] = {
  G5, G5, G6, G5, M1, G7,
  G5, G5, G6, G5, M2, M1,
  G5, G5, M5, M3, M1, G7, G6,
  M4, M4, M3, M1, M2, M1
};

// 乐谱 —— 哆啦A梦
xdata uint16 music_score_doraemon[] = {
  G5,M1,M1,M3,  M6,M3,M5,
  M5,M6,M5,M3,  M4,M3,M2,
  M6,M2,M2,M4,  M7,M7,M6,M5,
  M4,M4,M3,  M6,M7,M1,M2,
  
  G5,M1,M1,M3,  M6,M3,M5,
  M5,M6,M5,M3,  M4,M3,M2,
  M6,M2,M2,M4,  M7,M6,M5,
  M4,M4,M3,M2,  M7,M2,M1
};

// 播放指定乐谱
void play(uint16 *ps, uint16 len) {
  for(index = 0; index < len; index++) {
    launchBuzzer(ps[index], spot);
  }
  delay(1000);
}

void loop() {
  // 按下按键 1 播放 生日快乐
  if(P5_1 == 0 && pressed1 == 0) {
    pressed1 = 1;
    lenth = sizeof(music_score_birthday) / sizeof(uint16);
    play(music_score_birthday, lenth);
  } else if(P5_1 == 1 && pressed1 == 1) {
    pressed1 = 0;
  }
  
  // 按下按键 2 播放 哆啦A梦
  if(P5_2 == 0 && pressed2 == 0) {
    pressed2 = 1;
    lenth = sizeof(music_score_doraemon) / sizeof(uint16);
    play(music_score_doraemon, lenth);
  } else if(P5_2 == 1 && pressed2 == 1) {
    pressed2 = 0;
  }
}

void main(void) {
  setup();
  while(1){
    loop();
  }
}

有部分音阶不太对,可能是频率值弄错了,但影响不大!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1563052.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springJPA如果利用注解的方式 进行多表关联操作

前言:上一篇我写了个用JPA的Specification这个接口怎么做条件查询并且进行分页的,想学的自己去找一下 地址:springJPA动态分页 今天我们来写个 利用jpa的Query注解实现多表联合查询的demo 注意: 不建议在实际项目中用这玩意. 因为: 1. 用Query写的sql 可读性极差,给后期维护这…

C++读取bin二进制文件

C读取bin二进制文件 在C中&#xff0c;可以使用文件输入/输出流来进行二进制文件的读写操作&#xff0c;方便数据的保存和读写。 //C读取bin二进制文件 int read_bin() {std::ifstream file("data_100.bin", std::ios::in | std::ios::binary);if (file) {// 按照二…

go发布包到github

1. 首先&#xff0c;我们在github上创建一个公有仓库并clone到本地 git clone https://github.com/kmust-why/gdmp-token.git cd gdmp-token/ 2. 在gdmp-token工程中初始化go.mod&#xff0c;其中后面的链接要跟github上创建的仓库和你的用户名对应 go mod init github.com/…

手撕算法-有效的括号

描述 分析 使用栈&#xff0c;如果是左括号&#xff0c;入栈&#xff0c;如果是右括号&#xff0c;判断栈是否为空&#xff0c;不是空出栈并校验是否匹配&#xff0c;不匹配返回false。最后如果栈为空&#xff0c;返回true。 代码 class Solution {public boolean isValid(…

【Vue3源码学习】— CH2.6 effect.ts:详解

effect.ts&#xff1a;详解 1. 理解activeEffect1.1 定义1.2 通过一个例子来说明这个过程a. 副作用函数的初始化b. 执行副作用函数前c. 访问state.countd. get拦截器中的track调用e. 修改state.count时的set拦截器f. trigger函数中的依赖重新执行 1.3 实战应用1.4 activeEffect…

Pyhon 大模型常见的微调方式,LLMs常见的Finetune方式;chatglm3微调实战;大模型微调通俗易懂总结

一、 LLMs微调 微调&#xff08;Fine-tuning&#xff09;是指在一个已经训练好的神经网络模型基础上&#xff0c;使用额外的数据集或调整超参数&#xff0c;以实现特定任务的训练过程。在微调中&#xff0c;通常会固定预训练模型的大部分参数&#xff0c;只调整最后几层或特定层…

依赖倒转原则

1.1 MM请求电脑 MM电脑坏了&#xff0c;需要修电脑&#xff0c;是因为每次打开QQ,一玩游戏&#xff0c;机器就死了。出来蓝底白字的一堆莫名奇妙的英文。蓝屏死机了&#xff0c;估计内存有问题。 1.2 电话遥控修电脑 遥控修理电脑&#xff0c;打开内存条&#xff0c;两根内存…

前端JS商品规格组合

给定一个数组 let data [{name: "颜色",specs: ["白色", "黑色"],},{name: "尺寸",specs: ["14寸","15寸", "16寸"],},{name: "处理器",specs: ["i5", "i7", "i9&…

【Java代码审计】XXE漏洞

【Java代码审计】XXE漏洞 1.XXE漏洞概述2.Java中的XML常见接口3.XXE 漏洞审计4.XXE漏洞演示XMLReaderSAXReaderSAXBuilderDocumentBuilder 5.XXE漏洞修复 1.XXE漏洞概述 XXE 为 XML 外部实体注入。当应用程序在解析 XML 输入时&#xff0c;在没有禁止外部实体的加载而导致加载…

AdaBoost算法详解自用笔记(1)二分类问题举例分析

AdaBoost算法详解自用笔记&#xff08;1&#xff09;二分类问题举例分析 提升方法的思路 AdaBoost作为一种提升方法&#xff0c;其需要回答两个问题&#xff1a;一是每一轮如何改变训练数据的权重或概率分布&#xff1b;二是如何将弱分类器组合成一个强分类器。对于第一个问题…

Mybatis——一对一映射

一对一映射 预置条件 在某网络购物系统中&#xff0c;一个用户只能拥有一个购物车&#xff0c;用户与购物车的关系可以设计为一对一关系 数据库表结构&#xff08;唯一外键关联&#xff09; 创建两个实体类和映射接口 package org.example.demo;import lombok.Data;import …

2024如何做好跨境电商?7个步骤详细讲解

近几年来&#xff0c;随着互联网的发展&#xff0c;国内外的商业贸易越来越流畅&#xff0c;直播电商的火爆也带动着一大批相关的产业链发展&#xff0c;其中跨境电商就是尤为突出的一个。尽管在国内做跨境电商的企业数量非常之多&#xff0c;但仍有许多新人争相入局&#xff0…

Docker搭建LNMP环境实战(09):安装mariadb

1、编写mariadb部署配置文件 在文件夹&#xff1a;/mnt/hgfs/dockers/test_site/compose下创建文件&#xff1a;test_site_mariadb.yml&#xff0c;内容如下&#xff1a; version: "3.5" services:test_site_mariadb:container_name: test_site_mariadbimage: mari…

Android 自定义View 测量控件宽高、自定义viewgroup测量

1、View生命周期以及View层级 1.1、View生命周期 View的主要生命周期如下所示&#xff0c; 包括创建、测量&#xff08;onMeasure&#xff09;、布局&#xff08;onLayout&#xff09;、绘制&#xff08;onDraw&#xff09;以及销毁等流程。 自定义View主要涉及到onMeasure、…

Mybatis-自定义映射ResultMap用法

文章目录 一、处理属性名与字段名不同问题1.通过设置查询别名&#xff0c;使类属性名与字段名&#xff08;数据库内的名&#xff09;一致2.设置全局配置&#xff0c;使下划线自动映射为驼峰3.ResultMap 二、处理多对一映射问题前提背景1.使用级联来实现2.association 标签实现3…

Redis数据库常用命令和数据类型

文章目录 一、Redis数据库常用命令1、set/get2、keys3、exists4、del5、type6、rename6.1 重命名6.2 覆盖 7、renamenx8、dbsize9、密码设置10、密码验证11、查看密码12、取消密码13、Redis多数据库常用命令13.1 多数据库间切换13.2 多数据库间移动数据13.3 清除数据库数据 二、…

TSINGSEE青犀智慧工厂视频汇聚与安全风险智能识别和预警方案

在智慧工厂的建设中&#xff0c;智能视频监控方案扮演着至关重要的角色。它不仅能够实现全方位、无死角的监控&#xff0c;还能够通过人工智能技术&#xff0c;实现智能识别、预警和分析&#xff0c;为工厂的安全生产和高效运营提供有力保障。 TSINGSEE青犀智慧工厂智能视频监…

【Leetcode】331. 验证二叉树的前序序列化

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接&#x1f517; 序列化二叉树的一种方法是使用 前序遍历 。当我们遇到一个非空节点时&#xff0c;我们可以记录下这个节点的值。如果它是一个空节点&#xff0c;我们可以使用一个标记值记录&#x…

前端 - 基础 表单标签 - 表单元素 input - (name Value checked maxlength )属性详解

目录 name 属性 Value 属性 Checked 属性 Maxlength 属性 场景问答 # <input> 标签 除了 type 属性外&#xff0c;还有其他常用属性 >>> name 属性 在上一节 我们遇到的 单选按钮 &#xff0c;为什么 本应该 多选一 结果成了 多选多的问题 就…

HashMap考点相关源码解析

参考资料&#xff1a; HashMap超详细源码解析 - 掘金 HashMap常见面试题_hashmap面试题-CSDN博客 详解&#xff1a;HashMap红黑树的阈值为什么是8&#xff1f;_hashmap 红黑树阈值为什么是8-CSDN博客 史上最全HashMap源码整理-CSDN博客 HashMap源码和实现原理_hashmap源码…