Rain_Personal 发表于 2024-4-26 20:28:13

本帖最后由 Rain_Personal 于 2024-4-26 20:37 编辑

第九课 数码管的静态使用

1. 什么时数码管


数码管就是LED灯,根据发光二极管的正负极可以分为共阳和共阴数码管,LED灯负极接在一起的就是共阴,LED数码管正极接在一起的就是共阳





每个灯表示一个段,每8个灯表示一个位,根据课后作业推算出来的各个字母的描述其中N的描述应该时11.。没有想到其他方法,只能用dp区分了。




根据每个灯的控制逻辑可以将每个数字所需要亮的灯用16进制描述。
首先需要控制共阳/阴极开启一位显示,再根据16进制控制这一位的每个灯开关逻辑
P70 = 0;                        //开启一个数码管

就是开启一个数码管。


关键代码分析

Rain_Personal 发表于 2024-4-26 21:00:30

本帖最后由 Rain_Personal 于 2024-4-27 08:32 编辑

第十课动态显示数码管

1. 显示原理


其中需要注意每个延时不能太短,我们这边程序就以1ms为准,且需要保证总共一个循环结束的时间不能大于20ms,因为人眼的视觉不容易分辨出50HZ以上的动态刷新。



通过延时的长短可以控制每个灯的显示时间,超过人眼闪烁的分辨率就可以看起开像都显示了。
全部显示不同数字时,可以减少延时时间,看起来像是每位都在显示,其实是每位分别显示,只是频率快,人眼分辨不出来。
逻辑上有点绕,感觉比较复杂。
2. 10秒按键挑战代码分析


void SEG_Fre( void )   //应该是属于刷新数码管
{
      //位码选择第一位,段码选择0
      P7 = COM_Tab;                        //位码的选择
      P6 = SEG_Tab];//需要显示的数字的内码 赋给 P6   NUM =0 -> Show_Tab] = 1 -> p6 = oxF9
      delay_ms(SEG_Delay);

      num++;
      if( num >7 )
                num = 0;      
}


                Show_Tab= 1;                //选择 1
                Show_Tab= 10;                //选择 0.// 为什么从10开始,   带小数点
                Show_Tab= 0;                //选择 0
                Show_Tab= 0;                //选择 0                        

                if( RUN_State==1 )
                {
                        TimCount++;
                        Show_Tab = TimCount/10000%10;//TimCount/10000,表示有多少个10000,计算万位以上数字 %10 对10取余 表示万位上的数字
                        Show_Tab = TimCount/1000%10+10;      // 加10 带小数点
                        Show_Tab = TimCount/100%10;               
                  Show_Tab = TimCount/10%10;                //取10位
                }
               
                SEG_Fre();// 刷新数码管

                if( KEY1 ==0 )
                {
                        delay_ms(10);
                        if( KEY1 ==0 )
                        {
                              BEEP = 0;
                              delay_ms(10);
                              BEEP = 1;
                              while( KEY1 ==0 )
                              {
                                        SEG_Fre();
                              }
                              if( RUN_State==0 )
                                        TimCount = 0;
                              
                              RUN_State = !RUN_State;
                        }
                }

这逻辑秒呀!!!


Rain_Personal 发表于 2024-4-26 21:05:15

本帖最后由 Rain_Personal 于 2024-4-27 08:35 编辑

第十一课 定时器的应用

while(Key==0)会不断循环,函数不会向下运行。
1. 定时器作用



定时器主要是可以自动自增,定时时间,达到固定时间就可以执行想要的不在主程序中的程序段

void Timer0_Init(void)                //1毫秒@24.000MHz
{
      AUXR &= 0x7F;                        //定时器时钟12T模式   AUXR为寄存器0x8e 那么后面的都是寄存器的描述,直接赋值寄存器,就是初始化
      TMOD &= 0xF0;                        //设置定时器模式
      TL0 = 0x30;                              //设置定时初始值
      TH0 = 0xF8;                              //设置定时初始值
      TF0 = 0;                              //清除TF0标志
      TR0 = 1;                              //定时器0开始计时
      ET0 = 1;                              //使能定时器0中断
}


void Timer0_Isr(void) interrupt 1 // interrupt 关键字
{
      SEG_Fre();                //数码管刷新的
      
      if( RUN_State==1 )                //如果开始运行
      {      
                TimCount++;                        //每隔1ms+1
                Show_Tab = TimCount/10000%10;
                Show_Tab = TimCount/1000%10+10;      
                Show_Tab = TimCount/100%10;               
                Show_Tab = TimCount/10%10;                //取10位
      }
      
}


可以通过STCAI-ISP下载器中的所带的功能设置定时器
不使能定时器

void Timer0_Init(void)                //1毫秒@24.000MHz
{
      AUXR &= 0x7F;                        //定时器时钟12T模式
      TMOD &= 0xF0;                        //设置定时器模式
      TL0 = 0x30;                              //设置定时初始值
      TH0 = 0xF8;                              //设置定时初始值
      TF0 = 0;                              //清除TF0标志
      TR0 = 1;                              //定时器0开始计时
}

使能定时器ET0的寄存器使能定时器

void Timer0_Init(void)                //1毫秒@24.000MHz
{
      AUXR &= 0x7F;                        //定时器时钟12T模式
      TMOD &= 0xF0;                        //设置定时器模式
      TL0 = 0x30;                              //设置定时初始值
      TH0 = 0xF8;                              //设置定时初始值
      TF0 = 0;                              //清除TF0标志
      TR0 = 1;                              //定时器0开始计时
      ET0 = 1;                              //使能定时器0中断
}


Rain_Personal 发表于 2024-4-27 08:58:32

第十二课计数器的应用



使用SYSclk时,是计时器,SYSclk为固定频率,所以可以计数,理论仍是计数。
使用T1 Pin为计数器,可以对电机转速什么的进行计数

Rain_Personal 发表于 2024-4-27 10:05:20

本帖最后由 Rain_Personal 于 2024-4-27 11:48 编辑

第十三课简易多任务处理
1. 模块化编程
打开工程后。需要打开一个c文件才可以显示模块化编程中的模块







打开c文件之后




引脚定义可以用

sbit 名称 = P10;      
#define 名称 P10
作业:LED0给他200ms取反一次,LED1给他400ms取反一次,LED2给他800ms取反一次


关键代码
P40 = 0;
// 可采用中断控制LED0LED1 LED2
// LED0200ms



不能生成200ms的程序...



Rain_Personal 发表于 2024-4-27 11:56:15

第十四课矩阵键盘




SW33按下为什么是0,而不是P01是5V???
GND遇到5V会把引脚拉低到0V,而不是5V会把GND拉底到5V!

Rain_Personal 发表于 2024-4-27 14:35:31

第十五课 外部中断

1. 中断系统
多个中断源
2. 外部中断



外部引脚可以触发中断,INT标注的引脚为中断引脚
代码描述
需要首先定义中断 以中断0为例
        EA = 1;                                        //CPU开放中断,打开总中断。
        IT0 = 1;                                                //1:下降沿中断   0:上升下降沿中断
        EX0 = 1;                                                //允许中断
        IE0 = 0;                                                //清除中断标志位

void INT0_Isr(void) interrupt 0// 中断触发后执行的函数
{
        SEG0 += 1;                                        //数码管0的数值+1
}


Rain_Personal 发表于 2024-4-27 15:15:33

第十六课IO中断

IO中断于Pin的中断区别,中断里面不能添加延时函数。

Rain_Personal 发表于 2024-4-27 17:24:00

zhaoye818 发表于 2024-4-27 15:56
学习真认真

谢谢,非科班出身,只能死磕{:4_167:},共同进步

Rain_Personal 发表于 2024-4-27 18:02:20

本帖最后由 Rain_Personal 于 2024-4-28 18:17 编辑

第十七课模数转换器ADC

1. ADC原理


个人理解有点像递归调用,



使用ADC功能时,Vref引脚的单片机不能悬空,必须接外部参考电压源或者VCC!!! 是不是表明如果不接Vref就会烧毁单片机?





实验箱的采用的是2.5V基准电压

ADC接口需要设置为高阻输入相当于初始化ADC

P1M0 = 0x00;                                       //设置P10为高阻输入
P1M1 = 0x01;


ADCTIM = 0X3F;                                        //ADC内部时序
ADCCFG = 0X2F;                                        //数据右对齐,时钟选择位SYSCLK/2/16最慢
ADC_POWER = 1;                                        //打开adc电源



      u16ADC_Read( u8 no )// no 表示通道
      {
                u16 adcval;                                                                //adc数值保存变量
                ADC_CONTR &= 0xf0;                                                //清空通道
                ADC_CONTR |= no;                                                //选择通道
                ADC_START = 1;                                                      //开启ADC转化
                _nop_();                                                                //空操作指令    intrins.h
                _nop_();                        
                while(!ADC_FLAG);                                                //等待ADC转换结束
                ADC_FLAG = 0;               
                adcval = (ADC_RES << 8)+ ADC_RESL;      //计算adc的数值高8位 低8位用两个16进制描述12位的ADC值
                adc_val = adcval;
                return adcval;
      }

通道的选择 其中ADC_CHS表示通道,函数调用需要输入对应参数 0000~0111即0~7


实验箱中可以通过按键生成ADC值


SW1~SW16

获取真实电压值的计算方式为

u16 ADC_CAL_Voltage(u16 num)
{
        return num*2.5*1000 /4096; // num取值为0-4096    返回值为0-2500
}



页: 1 [2] 3 4 5
查看完整版本: 跟冲哥学习STC32G128K芯片打卡