陈畅南 发表于 2021-7-17 11:13:40

[天问STC8]单片机学习笔记(20210716&0717)

本来这两天是要学习PWM和ADC的,但是在学习的过程中发现了漏掉了按键输入的笔记内容,这次笔记一并放上。

目录
1、按键输入
2、PWM
3、ADC

陈畅南 发表于 2021-7-17 11:32:38

按键输入

    按键输入其实是一块比较简单的内容,在这里我也指先学习KEY1-4 这四个独立按键,而没有学矩阵按键。这里就直接上手编程。


1、

https://www.haohaodada.com/new/bbs/forum.php?mod=image&aid=1964&size=300x300&key=e79699638399761e&nocache=yes&type=fixnone
这个程序可以完成用KEY1-KEY4分别变量自锁控制8led中的前4个。
之所以编写这个程序,主要是了解自锁功能的实现。

2、
将1中的图形化编程语言转化为C语言编程。
发现led 的引脚要定义四遍,很繁琐,可以有更简单的处理方式。
https://www.haohaodada.com/new/bbs/forum.php?mod=image&aid=1966&size=300x300&key=0c9018e6cce268cd&nocache=yes&type=fixnone
不定义引脚,定义端口P_6
最后的输出代码改为
P6 = 0xff - ( 1 * temp0 + 2 * temp1 + 4 * temp2 + 8 * temp3 ) ;

一样可以实现1的效果

陈畅南 发表于 2021-7-17 11:58:58

PWM


1、基本原理
    在模拟世界中,电路的输入是下图这样子的正弦波。而在数字世界中,却做不到输出这类的正弦波
    https://pic2.zhimg.com/80/v2-a09867506ed6bb4dd98c903555e5fe8a_720w.jpg?source=1940ef5c

但是只要这个正弦波与t坐标轴围起来的阴影面积相同…
不管给你什么样形状的电压波形…
对你产生的效果都是大概一样的…
打个比方说…
老板让你三天每天工作8小时…
或者让你一天工作24小时再休息两天…
对你产生的苦逼感是一样的…

这就是面积等效原理


https://pic3.zhimg.com/80/v2-2b6dc955fcf03257717c26e36b7f7a93_720w.jpg?source=1940ef5c
上图的两种的电路输出效果是相似的。

PWM就是建立在面积等效原理之上,把输入的正弦直流电转化为一定频率的PWM“正弦波”。

我们调制出的交流电压值主要取决于我们所控制的占空比...
调制出来的交流电压的波形精度取决于我们所设定的载波频率...
而载波频率与调制出来交流电压的频率之比...
我们称之为载波比..。


2、脉冲宽度调制原理

一般数字设备(如MCU、DSP和FPGA) 可产生用于控制电机速度或者LED灯发光强度的脉冲宽度调制(PWM) 信号
对于PWM而言, 脉冲周期是恒定的。通常, 将一个脉冲周期内维持高电平的时间称为占空,通过数字设备可以改变占空值。占空比表示为

https://www.haohaodada.com/new/bbs/forum.php?mod=image&aid=1967&size=300x300&key=741484d8e96c3b7d&nocache=yes&type=fixnone

PWM信号的直流平均值与占空是成正比的。一个占空比为50%的PWM信号, 其直流值为PWM信号幅度最大值的1/2。因此, 通过改变PWM的占空比, 就可以改变PWM信号中所含直流信号分量的大小。
    通过模拟有源/无源低通滤波器, 就可以从PWM信号中提取出直流分量。如果将这个直流分量进行功率放大,并施加在直流电机的两端,就可以改变直流电机的转速。因此,PWM是连接数字世界与模拟世界的桥梁, 其作用就类似于数模转换器DAC。

陈畅南 发表于 2021-7-17 15:06:33

PWM
3、PWM的应用。
    在开发板中,PWM主要应用在蜂鸣器和小电机中。接下来编两个程序来进行实验。
   
(1)调速小马达



https://www.haohaodada.com/new/bbs/forum.php?mod=image&aid=1968&size=300x300&key=52259883d5888583&nocache=yes&type=fixnone

通过这个小马达程序探究占空比和和输出的关系。
这个程序的输出结果是电机由慢到快再由快到慢转动。占空比的原理是
https://www.haohaodada.com/new/bbs/forum.php?mod=image&aid=1969&size=300x300&key=08038c448fab635b&nocache=yes&type=fixnone

占空比越大,在一个脉冲周期中高电平的时间就越长。结果就是输出越高,在程序中i达到1000时,小电机转速最快,随后慢慢降低。

(2)蜂鸣器
    理论上来说,利用PWM,可以通过蜂鸣器编出一个乐曲。
    我在网络上找到了一个声调和频率的关系图。定义这些常量之后方便输入乐谱。
https://www.haohaodada.com/new/bbs/forum.php?mod=image&aid=1970&size=300x300&key=fd69eafc47e880c2&nocache=yes&type=fixnone
定义一个全局变量数组并在里面编曲。
https://www.haohaodada.com/new/bbs/forum.php?mod=image&aid=1971&size=300x300&key=4f981acbaeab0aad&nocache=yes&type=fixnone
这个函数用来播放
void loop()
{
for (i = (0); i < (sizeof(song)/sizeof(song)); i = i + 1) {
    pwm_freq_duty(PWM5_P00, song[(int)(i)], 200);//pwm调整三个参数分别是引脚、频率、占空比10/PWM_DUTY_MAX
    delay(durt[(int)(i)]);
    //
}
}

运行测试,没问题。之后就可以自己想编什么曲编什么了。

附代码:
#define PWM_DUTY_MAX 1000//PWM最大占空比值
#define Do 495
#define Re 556
#define Mi 624
#define Fa 661
#define Sol 742
#define La 833
#define Si 935
#define hDo 990
#define hRe 1112
#define hMi 1178
#define hFa 1322
#define hSol 1484
#define hLa 1665
#define hSi 1869
#define dDo 248
#define dRe 278
#define dMi 294
#define dFa 330
#define dSol 371
#define dLa 416
#define dSi 467


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


uint16 i = 0;


code uint16 song[]={dMi, dFa, dSol, dLa, Mi, Do, Re, Do, dMi, dFa, dSol, dLa, Mi, Do, dLa, Re, Mi, dMi, dFa, dSol, dLa, Mi, Do, dLa, };
code uint16 durt[]={250,250, 250, 250, 500, 250, 750, 750, 250, 250, 250, 250, 500, 250,250,750,750,250,250,250,250,600};


void setup()
{
twen_board_init();//天问51初始化
pwm_init(PWM5_P00, 1000, 300);//pwm初始化三个参数分别是引脚、频率、占空比10/PWM_DUTY_MAX
}


void loop()
{
for (i = (0); i < (sizeof(song)/sizeof(song)); i = i + 1) {
    pwm_freq_duty(PWM5_P00, song[(int)(i)], 200);//pwm调整三个参数分别是引脚、频率、占空比10/PWM_DUTY_MAX
    delay(durt[(int)(i)]);
    //
}
}


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


陈畅南 发表于 2021-7-19 10:50:38

ADC


1、基本介绍。
    PWM是模拟信号转化成数字信号再进行输出,而ADC就是把模拟信号转化为数字信号进行输入。
   
2、ADC的时钟频率和位数。
    ADC 的时钟频率为系统频率 2 分频再经过用户设置的分频系数进行再次分频(ADC的时钟频率范围为 SYSclk/2/1~SYSclk/2/16)。ADC的位数,如果 10 位 AD,采样值范围为 0-1023;12 位 AD,采样值范围为 0-4095;根据具体需求进行选择


3、ADC的应用。
    (1)在使用ADC之前,先介绍一下3个板载模拟量输出传感器。
    A、电位器。
    电位器是具有三个引出端、阻值可按某种变化规律调节的电阻元件。电位器通常由电阻体和可移动的电刷组成。当电刷沿电阻体移动时,在输出端即获得与位移量成一定关系的电阻值或电压。
芯片图:

https://www.haohaodada.com/new/bbs/forum.php?mod=image&aid=1972&size=300x300&key=0dacac306d0d7a28&nocache=yes&type=fixnone

    B、NTC
    热敏电阻。
芯片图:
https://www.haohaodada.com/new/bbs/forum.php?mod=image&aid=1974&size=300x300&key=29aeb2aa9e1116bc&nocache=yes&type=fixnone

    C、LIGHT
    光敏电阻。
芯片图:
https://www.haohaodada.com/new/bbs/forum.php?mod=image&aid=1973&size=300x300&key=93e6967f057b4868&nocache=yes&type=fixnone

陈畅南 发表于 2021-7-19 11:20:41

ADC的应用

1、数码管显示电位器数值
    https://www.haohaodada.com/new/bbs/forum.php?mod=image&aid=1975&size=300x300&key=8a84f4c42182f88c&nocache=yes&type=fixnone
    先用图形化编程。在ADC的定义中设置为2分频、8位

    点击运行,调节电位器的旋钮,发现数码管的数值在0-255之间显示。

    再定义ADC为2分频、12位,点击运行,发现数码管的数值显示范围在0-4095

https://www.haohaodada.com/new/bbs/forum.php?mod=image&aid=1976&size=300x300&key=f5ff4cf13ad9055b&nocache=yes&type=fixnone

    定义ADC为32分频,12位,点击运行,发现数码管的数值显示范围还在0-4095,基本没有变化。


https://www.haohaodada.com/new/bbs/forum.php?mod=image&aid=1977&size=300x300&key=bc15344645d997b6&nocache=yes&type=fixnone

    分频是将输入信号的频率降低再进行输出。输出信号的频率是输入信号的几分之几,这个电路就是几分频。分频越高,速度越慢,位数越高,精度越高。而在32分频中,肉眼实际上难以分辨分频改变带来的速度变化,所以我们看起来什么都没变。

2、数码管显示亮度。

#define NIXIETUBE_PORT P6
#define NIXIETUBE_PORT_MODE {P6M1=0x00;P6M0=0xff;}//推挽输出
#define NIXIETUBE_LEFT_COLON_PIN P0_7//左侧数码管冒号
#define NIXIETUBE_LEFT_COLON_PIN_MODE {P0M1&=~0x80;P0M0|=0x80;}//推挽输出
#define NIXIETUBE_RIGHT_COLON_PIN P2_1//右侧数码管冒号
#define NIXIETUBE_RIGHT_COLON_PIN_MODE {P2M1&=~0x02;P2M0|=0x02;}//推挽输出


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


void Timer0Init(void)        //1000微秒@24.000MHz
{
AUXR &= 0x7f;                //定时器时钟12T模式
TMOD &= 0xf0;                //设置定时器模式
TL0 = 0x30;                        //设定定时初值
TH0 = 0xf8;                        //设定定时初值
}


void T_IRQ0(void) interrupt 1 using 1{
nix_scan_callback();//数码管扫描回调函数
}


void setup()
{
twen_board_init();//天问51初始化
adc_init(ADC_P06, ADC_SYSclk_DIV_2, ADC_12BIT);//ADC初始化,三个参数ADC引脚,时钟分频双数2-32,输出值位数12BIT最大分率-12位的ADC输出12位,10位的输出10位
led8_disable();//关闭8个LED流水灯电源
nix_init();//数码管初始化
Timer0Init();
TR0 = 1;// 定时器0开始计时
EA = 1; // 控制总中断
ET0 = 1; // 控制定时器中断
}


void loop()
{
nix_display_clear();//数码管清屏
nix_display_num((adc_read(ADC_P06)));//数码管显示整数
delay(10);
}


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

点击运行,数码管数值显示在200-300之间,拿手遮挡光敏电阻,数值下降到20左右,拿手机手电筒照射光敏电阻,数值上升到2500左右。

chenshimei 发表于 2021-9-10 14:45:48

学到了,谢谢!:victory:
页: [1]
查看完整版本: [天问STC8]单片机学习笔记(20210716&0717)