查看: 154|回复: 6

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

[复制链接]

6

主题

40

帖子

112

积分

注册会员

Rank: 2

积分
112
发表于 2021-7-17 11:13:40 | 显示全部楼层 |阅读模式
本来这两天是要学习PWM和ADC的,但是在学习的过程中发现了漏掉了按键输入的笔记内容,这次笔记一并放上。

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

使用道具 举报

6

主题

40

帖子

112

积分

注册会员

Rank: 2

积分
112
 楼主| 发表于 2021-7-17 11:32:38 | 显示全部楼层
按键输入

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


1、


这个程序可以完成用KEY1-KEY4分别变量自锁控制8led中的前4个。
之所以编写这个程序,主要是了解自锁功能的实现。

2、
将1中的图形化编程语言转化为C语言编程。
发现led 的引脚要定义四遍,很繁琐,可以有更简单的处理方式。

不定义引脚,定义端口P_6
最后的输出代码改为
P6 = 0xff - ( 1 * temp0 + 2 * temp1 + 4 * temp2 + 8 * temp3 ) ;

一样可以实现1的效果

1.PNG
1.1.PNG
1.2.PNG
回复

使用道具 举报

6

主题

40

帖子

112

积分

注册会员

Rank: 2

积分
112
 楼主| 发表于 2021-7-17 11:58:58 | 显示全部楼层
PWM


1、基本原理
    在模拟世界中,电路的输入是下图这样子的正弦波。而在数字世界中,却做不到输出这类的正弦波
   

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

这就是面积等效原理



上图的两种的电路输出效果是相似的。

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

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


2、脉冲宽度调制原理

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



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

2.1.PNG
回复

使用道具 举报

6

主题

40

帖子

112

积分

注册会员

Rank: 2

积分
112
 楼主| 发表于 2021-7-17 15:06:33 | 显示全部楼层
PWM
3、PWM的应用。
    在开发板中,PWM主要应用在蜂鸣器和小电机中。接下来编两个程序来进行实验。
   
(1)调速小马达





通过这个小马达程序探究占空比和和输出的关系。
这个程序的输出结果是电机由慢到快再由快到慢转动。占空比的原理是


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

(2)蜂鸣器
    理论上来说,利用PWM,可以通过蜂鸣器编出一个乐曲。
    我在网络上找到了一个声调和频率的关系图。定义这些常量之后方便输入乐谱。

定义一个全局变量数组并在里面编曲。
[url=][/url]
这个函数用来播放
void loop()
{
  for (i = (0); i < (sizeof(song)/sizeof(song[0])); 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[0])); 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();
  }
}


3.3.PNG
3.2.PNG
2.1.PNG
3.1.PNG
回复

使用道具 举报

6

主题

40

帖子

112

积分

注册会员

Rank: 2

积分
112
 楼主| 发表于 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、电位器。
    电位器是具有三个引出端、阻值可按某种变化规律调节的电阻元件。电位器通常由电阻体和可移动的电刷组成。当电刷沿电阻体移动时,在输出端即获得与位移量成一定关系的电阻值或电压。
芯片图:



    B、NTC
    热敏电阻。
芯片图:


    C、LIGHT
    光敏电阻。
芯片图:

4.3.png
4.2.png
4.1.png
回复

使用道具 举报

6

主题

40

帖子

112

积分

注册会员

Rank: 2

积分
112
 楼主| 发表于 2021-7-19 11:20:41 | 显示全部楼层
ADC的应用

1、数码管显示电位器数值
   
    先用图形化编程。在ADC的定义中设置为2分频、8位

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

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



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




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

2、数码管显示亮度。

#define NIXIETUBE_PORT P6
#define NIXIETUBE_PORT_MODE {P6M1=0x006M0=0xff;}//推挽输出
#define NIXIETUBE_LEFT_COLON_PIN P0_7//左侧数码管冒号
#define NIXIETUBE_LEFT_COLON_PIN_MODE {P0M1&=~0x800M0|=0x80;}//推挽输出
#define NIXIETUBE_RIGHT_COLON_PIN P2_1//右侧数码管冒号
#define NIXIETUBE_RIGHT_COLON_PIN_MODE {P2M1&=~0x022M0|=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左右。

5.3.PNG
5.2.PNG
5.1.PNG
回复

使用道具 举报

1

主题

6

帖子

85

积分

注册会员

Rank: 2

积分
85
发表于 2021-9-10 14:45:48 | 显示全部楼层
学到了,谢谢!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|好好搭搭在线 ( © 好好搭搭在线 浙ICP备19030393号-1 )

GMT+8, 2021-10-18 10:21 , Processed in 0.291924 second(s), 25 queries .

Powered by Discuz!

© 2001-2021 Comsenz Inc.

快速回复 返回顶部 返回列表