yzk_hi 发表于 2024-4-29 08:50:20

打卡十三集

组织小白 发表于 2024-4-29 09:24:12

科学妞妞 发表于 2024-4-29 08:33
就是按时间的流水,操作逻辑运算,按步骤,有中断的时候,按中断,知道大概个意思,知道有寄存器这回事, ...

{:victory:}

组织小白 发表于 2024-4-29 09:24:46

科学妞妞 发表于 2024-4-29 08:34
加油

{:victory:}

Rain_Personal 发表于 2024-4-29 11:18:48

后面越来越难了

好学天上 发表于 2024-4-29 11:50:44

第十四集矩阵按键打卡,胜利就在不远处!{:victory:}
STC32G128K芯片学习打卡贴
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=7834
(出处: 国芯技术交流网站)

bnnpyuvtkd 发表于 2024-4-29 13:46:42

本帖最后由 bnnpyuvtkd 于 2024-4-29 16:10 编辑

      第17讲:模数转换器ADC上
      1、数模转换器是什么?
      2、STC32G单片机ADC使用原理
                一、ADC相关的寄存器
                (1)、ADC控制寄存器(ADC_CONTR) , PWM触发ADC控制
符号                   地址      B7                     B6                      B5                   B4                      B3   B2   B1B0
ADC_CONTR      BCH      ADC_POWER      ADC_START      ADC_FLAG      ADC_EPWMT      ADC_CHS
      ADC_POWER:ADC 电源控制位
                0:关闭ADC电源
                1:打开ADC电源
                建议进入空闲模式和掉电模式前将ADC电源关闭,已将低功耗
                特别注意:
                        1、给MCU的内部ADC模块电源打开后,需等待约1ms,等MCU内部的ADC电源稳定后再让ADC工作:
                        2、适当加长对外部信号的采样时间,就是对ADC内部采样保持电容的充电或放电时间,时间够,内部才能和外部电势相等。
      ADC_START:ADC转换启动控制位。写入1后开始ADC转换,转换完成后硬件自动将此位清0 。
                0:无影响。即使ADC已经开始转换工作,写0也不会停止A/D转换。
                1:开始ADC转换,转换完成后硬件自动将此位清0 。
      ADC_FLAG:ADC转换结束标志位。当ADC完成一次转换后,硬件会自动将此位置1 ,并向CPU提出中断要求。此标志位必须软件清0 。
      ADC_EPWMT:使能PWM实时触发ADC功能。详情请参考16位高级PWM定时器章节。
      ADC_CHS:ADC模拟通道选择位。
      (注意:被选择为ADC输入通道的I/O口,必须设置PxM0/PxM1寄存器将I/O口设置为高阻输入模式。另外如果MCU进入主时钟停振/省电模式后,仍需要使能ADC通道,则需要设置PxIE寄存器关闭数字输入通道,以防止外部模拟输入信号忽高忽低而产生额外的功耗)
ADC_CHS   ADC通道    ADC_CHS      ADC通道
0000                   P1.0                1000                P0.0
0001                   P1.1                1001                P0.1
0010                   P1.2/P5.4      1010               P0.2
0011                   P1.3                1011                P0.3
0100                   P1.4                1100                P0.4
0101                   P1.5                1101                P0.5
0110                   P1.6                1110                P0.6
0111                   P1.7                1111               测试内部1.19V
有P1.2口的型号,此功能在P1.2口上,对于无P1.2口的型号,此功能在P5.4扣上。特别是:STC32G8K64系列的ADC通道2在P5.4

                (2)、ADC配置寄存器(ADCCFG)
符号      地址      B7      B6      B5      B4      B3      B2      B1      B0
ADCCFG      DEH      -      -      RESFMT      -      SPEED
RESFMT:ADC转换结果格式控制位
                0:转换结果左对齐。ADC_RES保存结果的高8位,ADC_RESL保存结果的低4位。格式如下:
                      ADC_RES                                                                   ADC_RESL
      D11,D10,D9,D8,D7,D6,D5,D4             D3,D2,D1,D0, 0,0,0,0
   1_______________________________________________________11_________1
                                    12位换算结果                                                      自动添0
                                                 RESFMT = 0

               1:换算结果右对齐。ADC_RES保存结果的高4位,ADC_RESL保存结果的低8位。格式如下:
                           ADC_RES                                                      ADC_RESL
                0 ,0 ,0 ,0 ,D11,D10,D9,D8                D7,D6,D5,D4,D3,D2,D1,D0
            1__________1    1_______________________________________________________1
                   自动添0                                       12位换算结果
                                          RESFMT = 1


SPEED:设置ADC时钟{FADC=SYSclk/2/(SPEED+1)}
SPEED      ADC时钟频率
0000               SYSclk/2/1
0001               SYSclk/2/2
0010               SYSclk/2/3
______               ______
1101               SYSclk/2/14
1110               SYSclk/2/15
1111               SYSclk/2/16


                (3)、ADC转换结果寄存器(ADC_RES,ADC_RESL)
符号               地址      B7      B6      B5      B4      B3      B2      B1      B0
ADC_RES          BDH      
ADC_RESL      BDH      
                当A/D转换完成后,转换结果会自动保存到ADC_RES和ADC_RESL中。保存结果的数据格式请参考ADC_CFG寄存器中的RESFMT设置。

                (4)、ADC时序控制寄存器(ADCTIM)
符号               地址             B7                  B6      B5      B4B3B2B1B0
ADCTIM      7EFEA8H      CSSETUP      CSHOLD      SMPDUTY
      CSSETUP:ADC通道选择时间控制Tsetup
CSSETUP      ADC时钟
0                   1(默认值)
1                   2
      CSHOLD:ADC通道选择保持时间控制Thold
CSHOLD      ADC时钟数
00                     1
01                     2(默认值)
10                     3
11                     4
      SMPDUTY:ADC模拟信号采样时间控制Tcuty(注意:SMPDUTY一定不能设置小于01010B)
SMPDUTY      ADC时钟数
00000                      1
00001                      2
....                           ....
01010                     11(默认值)
....                           ....
11110                     31
11111                     32


                二、ADC整体转换时序图
      ADC模拟转换时间:Tconvert
      12位ADC的转换时间固定为12个ADC工作时钟
      一个完整的ADC转换时间为:Tsetup + Tduty + Thold + Tconvert,如下图所示


      3、ADC静态特征
      
   
   
符号描述最小值典型值最大值单位
RES分辨率 12 Bits
ET整体误差 0.51LSB
Eo偏移误差 -0.11LSB
EG增益误差 1LSB
Eo微分非线性误差 0.71.5LSB
E1积 分非线性误差 2LSB
RAIN通道等效电阻
      00 ohm



       

                                 


      4、ADC相关计算公式
      (1)、ADC速度计算公式
      ADC的转换速度由ADCCFG寄存器中的SPEED和ADCTIM寄存器共同控制。转换速度的计算公式如下所示:

                                                                     MCU工作频率SYSclk
      12位ADC转换速度=————————————————————————————————————————
                                    2 x (SPEED + 1) x [(CSSETUP + 1) + (CSHOLD + 1) + (SMPDUTY + 1) + 12]

注意:
      12位ADC的速度不能高于 800KHz
      SMPDUTY的值不能小于10,建议设置为15
      CSSETUP可使用上电默认值0
      CHOLD可使用上电默认值1(ADCTIM建议设置为3FH)

      (2)、ADC转换结果计算公式
                                                                  ADC被转换通道的输入电压Vin
                        12位ADC转换结果 = 4096 x ————————————————— (有独立ADC_Vref + 管脚)
                                                                        ADC外部参考源的电压

      (3)、反推ADC输入电压计算公式
                                                                                              12位ADC转换结果
      ADC被转换通道的输入电压Vin = ADC外部参考源的电压 x ———————————— (有独立ADC_Vref + 管脚)
                                                                                                   4096

      (4)、反推工作电压计算公式
      当需要使用ADC输入电压和ADC转换结果反推工作电压时,若目标芯片无独立的ADC+Vref + 管脚,则可直接测量并使用下面公式,若目标芯片有独立ADC_Vref + 管脚时,则必须将ADC_Vref + 管脚连接到 Vcc 管脚。
                                                                  ADC被转换通道的输入电压Vin
                        MCU工作电压Vcc = 4096 x —————————————————
                                                                        12位ADC转换结果

      5、ADC应用参考线路图
      (1)、一般精度ADC参考线路图




      (2)、高精度ADC参考线路图






      6、 STC—ISP | ADC转换速度计算器工具






      首先复制第16讲的“12、IO口中断”的代码,把第16讲的工程复制过来,改名为“13、ADC采集”,在“HARDWARE”文件夹中新建“ADC”文件夹,在文件夹里新建adc.c和adc.h两个文件,adc.c里填写如下程序:
#include "adc.h"
#include "intrins.h"

//=======================================================================
//函数名称:ADC_Init
//函数功能:ADC初始化
//入口参数:
//函数返回:
//当前版本:
//修改日期:
//当前作者:
//其他备注:
//=========================================================================

void ADC_Init(void)
{
      P1M0 = 0x00;                        //设置P10为高阻输入
      P1M1 = 0x00;
      
      ADCTIM = 0X3F;
      ADCCFG = 0X2F;                        //数据右对齐,时钟选择位SYSCLK/2/16 最慢
      ADC_POWER = 1;                        //打开adc电源
}


//=======================================================================
//函数名称:ADC_Read
//函数功能:读取指定通道的adc电压
//入口参数:@no :通道0~15
//函数返回:当前的12位adc数值
//当前版本:VER1.0
//修改日期:2023
//当前作者:
//其他备注:
//=========================================================================

u16 ADC_Read(u8 no)
{
      u16 adcval;                        //adc数值保存变量
      ADC_CONTR &= 0xf0;      //清空通道
      ADC_CONTR |= no;      //选择通道
      ADC_START = 1;                //开启ADC转化
      _nop_();
      _nop_();
      while(!ADC_FLAG);
      ADC_FLAG = 0;
      adcval = (ADC_RES << 8) + ADC_RESL;                //计算adc的值
      
      return adcval;
}

adc.h填写如下程序:

#ifndef __ADC_H
#define __ADC_H

#include "COMM/stc.h"                //调用头文件
#include "COMM/usb.h"

//------------------------------引脚定义------------------------------


//------------------------------变量声明------------------------------



//------------------------------函数声明------------------------------
void ADC_Init(void);                        //ADC初始化
u16 ADC_Read(u8 no);                        //读取指定通道的adc电压


#endif

Demo.c改写为如下程序:

#include "COMM/stc.h"                //调用头文件
#include "COMM/usb.h"
#include "seg_led.h"
#include "key.h"
#include "beep.h"
#include "tim0.h"
#include "exit.h"
#include "adc.h"


#define MAIN_Fosc 24000000UL      //定义主时钟

char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";

bitTIM_10MS_Flag;                        //10ms的标志位

void sys_init();      //函数声明
void delay_ms(u16 ms);      //unsigned int


void main()                                        //程序开始运行的入口
{
      u16 ADC_VAL;                        //ADC的数值
      
      sys_init();                              //USB功能+IO口初始化
      usb_init();                              //usb库初始化

      Timer0_Init();                        //定时器0初始化
      ADC_Init();
      
      EA = 1;                                        //CPU开放中断,打开总中断。
      
      LED = 0xff;                              //初始状态熄灭所有LED
      
      while(1)                //死循环
      {
                delay_ms(2);
                if( DeviceState != DEVSTATE_CONFIGURED )         //
                        continue;
                if( bUsbOutReady )                                                               
                {
                        usb_OUT_done();
                }
               
                if(TIM_10MS_Flag==1)                //如果10ms到了
                {
                        TIM_10MS_Flag = 0;                //清空标志位
                }
                ADC_VAL = ADC_Read(0);                //保存ADC的数值
                printf("当前ADC数值:%d\r\n\xfd",(int)ADC_VAL);                //串口打印ADC数值

      }
}

void Timer0_Isr(void) interrupt 1
{
      static timcount = 0;
      
      SEG_LED_Show();                        //数码管刷新的
      
      timcount++;                              //1ms+1
      if( timcount>=10 )                //如果这个变量大于等于10,10ms计数到达
      {
                timcount = 0;
                TIM_10MS_Flag = 1;      //10ms时间到了
      }
}


void sys_init()                //函数定义
{
    WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

      P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
      
    P3M0 = 0x00;
    P3M1 = 0x00;
   
    P3M0 &= ~0x03;
    P3M1 |= 0x03;

    //设置USB使用的时钟源
    IRC48MCR = 0x80;    //使能内部48M高速IRC
    while (!(IRC48MCR & 0x01));//等待时钟稳定

    USBCLK = 0x00;      //使用CDC功能需要使用这两行,HID功能禁用这两行。
    USBCON = 0x90;
}


void delay_ms(u16 ms)      //unsigned int
{
      u16 i;
      do
      {
                i = MAIN_Fosc/6000;
                while(--i);
      }while(--ms);
}

编译成功后,0错误0警告,在Objects文件夹中产生Demo.hex文件,下载到STC32G试验箱9.6中,在STCAI-ISP中的串口项目中,能看到ADC的数值。


jason813 发表于 2024-4-29 13:48:57

跟冲哥学stc,最新stc学起来

jason813 发表于 2024-4-29 14:02:04

第一集:30岁+上班也能学 跟着冲哥学一手{:lol:}

jason813 发表于 2024-4-29 14:52:57

第二集:学了第二集了解了 电磁炉,豆浆机都是单片机的应用,继续冲

好学天上 发表于 2024-4-29 17:14:45

第十五集外部中断打卡!!! 这真是激动人心的时刻{:lol:}
STC32G128K芯片学习打卡贴
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=7834
(出处: 国芯技术交流网站)
页: 173 174 175 176 177 178 179 180 181 182 [183] 184 185 186 187 188 189 190 191 192
查看完整版本: 视频教学:《32位8051单片机原理及应用》,一等奖2万, 送实验箱; 冲哥版