CListery 发表于 2024-6-27 15:26:16

第八课:
1. 学习在代码中通过 IRC 时钟写一个延时函数
2. 学习 #define 和 typedef 的使用
3. 学习点亮和熄灭发光二极管
4. 学习 while 和 do...while 循环语句
5. 学习 自减(--a) 的用法

CListery 发表于 2024-6-27 16:00:18

第九课:
1. 学习函数的定义、声明和使用
2. 学习模块化代码编写方式
3. 学习在 Keil 中添加 include path

CListery 发表于 2024-6-27 16:13:06

第十课:
1. 学习按键的种类、样式、和触发原理
2. 学习如何通过代码给按键消抖
3. 学习通过 if 条件判断语句和延时实现长按按键时间隔多久连续出发某个代码流程
4. 学习通过 while 循环控制语句实现避免长按按键时重复多次出发同一代码流程

CListery 发表于 2024-6-27 16:50:16

本帖最后由 CListery 于 2024-6-27 17:07 编辑

第十一课:
1. 学习通过按键控制 LED 灯的变化
2. 学习数组的使用
3. 拓展练习,通过位运算实现按键按一下 LED 位移一个位置

typedef unsigned char u8;

#define LED_LINE P2

sbit TIGGER = P1^7;

void main()
{

LED_LINE = 0xFE;
while(1)
{
    if(TIGGER == 0)
    {
      delay_ms(10);
      if(TIGGER == 0)
      {
      u8 v = ~LED_LINE;
      v = v << 1;
      if(v == 0)
      {
          v = 0x01;
      }
      LED_LINE = ~v;
      while(TIGGER == 0);
      }
    }
}
}4. 扩展练习,通过数组实现来回流水灯效果,长按触发,释放暂停
typedef unsigned char u8;

#define LED_LINE P2

sbit TIGGER = P1^7;

u8 LED_DATA = {
0xFE, 0xFD, 0xFB, 0xF7,
0xEF, 0xDF, 0xBF, 0x7F,
0xBF, 0xDF, 0xEF, 0xF7,
0xFB, 0xFD
};

void main()
{
u8 count = 0;
LED_LINE = LED_DATA;
while(1)
{
    if(TIGGER == 0)
    {
      delay_ms(10);
      if(TIGGER == 0)
      {
      LED_LINE = LED_DATA;
      delay_ms(500);
      //while(TIGGER == 0);
      }
    }
}
}



CListery 发表于 2024-6-27 23:58:46

本帖最后由 CListery 于 2024-6-28 00:09 编辑

第十二和十三集:
1. 了解蜂鸣器常见种类:有源、无源
2. 学习蜂鸣器的使用方法
3. 学习通过代码实现按键触发有源蜂鸣器发声
4. 实现电磁炉控制面板功能

#include "delay.h"

#define FUN_LINE P0

sbit POWER_KEY = P1^6;
sbit FUN_SW_KEY = P1^7;

sbit BEE = P2^7;

sbit ON_STATE = P3^0;

typedef unsigned char u8;

unsigned char FUN_DATA = {
0xFE, 0xFD, 0xFB, 0xF7,
0xEF, 0xDF, 0xBF, 0x7F
};

void buzzing(u8 ms)
{
BEE = 1;
delay_ms(ms);
BEE = 0;
}

void main()
{
u8 FUN_POS = 0; // 功能位下标
ON_STATE = 1;
BEE = 0;
while(1)
{
    FUN_LINE = 0xFF;
    if(POWER_KEY == 0)
    {
      delay_ms(10);
      if(POWER_KEY == 0)
      {
      while(!POWER_KEY);
      ON_STATE = 0;
      FUN_LINE = 0x00;
      buzzing(10);
      delay_ms(190);
      FUN_LINE = 0xFF;
      FUN_POS = 0;
      while(ON_STATE == 0)
      {
          if(POWER_KEY == 0)
          {
            delay_ms(10);
            if(POWER_KEY == 0)
            {
            while(!POWER_KEY);
            buzzing(10);
            ON_STATE = 1;
            break;
            }
          }
          else if(FUN_SW_KEY == 0)
          {
            delay_ms(10);
            if(FUN_SW_KEY == 0)
            {
            while(!FUN_SW_KEY);
            FUN_LINE = FUN_DATA;
            ++FUN_POS;
            buzzing(10);
            }
          }
      }
      }
    }
}
}



CListery 发表于 2024-6-28 10:06:41

本帖最后由 CListery 于 2024-6-28 11:42 编辑

第十四和十五课:
1. 学习数码管种类(型号后缀是A为共阳极,K为共阴极)及使用方式
2. 学习数码管刷新原理
3. 共阴8位数码管位移

typedef unsigned char BYTE;
typedef unsigned int WORD;

void delay_ms(BYTE ms)
{
BYTE i;
while(ms--)
{
    for(i=0;i<120;i++);
}
}

void delay_sec(WORD sec)
{
WORD i;
while(sec--)
{
    i = 0;
    while(++i);
}
}

#define SHARE P2

#define CONTROL P0

void main()
{
SHARE = 0x7F;
CONTROL = 0x3F;
while(1)
{
    delay_sec(1);
    SHARE = ~(~SHARE >> 1);
    if(SHARE == 0xFF)
      SHARE = 0x7F;
}
   
}
4. 共阴极数码管从0-9显示,从右往左循环播放

#define SHARE P2

#define CONTROL P0

BYTE NUM_MAP = {
0x3F, //   0
0x6, //1
0x5B, //   2
0x4F, //   3
0x66, //   4
0x6D, //   5
0x7D, //   6
0x7, //7
0x7F, //   8
0x6F, //   9
};

void main()
{
BYTE NUM_POS = 0;
SHARE = 0x7F;
CONTROL = NUM_MAP;
while(1)
{
    for(NUM_POS = 0; NUM_POS < 10; NUM_POS++)
    {
      CONTROL = NUM_MAP;
      delay_ms(500);
    }
    SHARE = ~(~SHARE >> 1);
    if(SHARE == 0xFF)
      SHARE = 0x7F;
}

}
5. 共阴极8位数码管加、减、归零功能计数器

#define SHARE P2

#define CONTROL P0

sbit ADD_TIGGER = P3^0;
sbit SUB_TIGGER = P3^1;
sbit ZERO_TIGGER = P3^2;

BYTE NUM_MAP = {
0x3F, //   0
0x6, //1
0x5B, //   2
0x4F, //   3
0x66, //   4
0x6D, //   5
0x7D, //   6
0x7, //7
0x7F, //   8
0x6F, //   9
};

BYTE UNIT_MAP = {
0x7F,
0xBF,
0xDF,
0xEF,
0xF7,
0xFB,
0xFD,
0xFE,
};

void shadowDelay()
{
delay_ms(1);// 产生残影
}

void main()
{
unsigned long PASS_COUNT = 0;
while(1)
{
    if(ADD_TIGGER == 0)
    {
      delay_ms(10);
      if(ADD_TIGGER == 0)
      {
      PASS_COUNT++;
      delay_ms(500);
      }
    }
    else if(SUB_TIGGER == 0)
    {
      delay_ms(10);
      if(SUB_TIGGER == 0)
      {
      PASS_COUNT--;
      delay_ms(500);
      }
    }
    else if(ZERO_TIGGER == 0)
    {
      delay_ms(10);
      if(ZERO_TIGGER == 0)
      {
      PASS_COUNT = 0;
      }
    }
   
    if(PASS_COUNT >= 99999999)
      PASS_COUNT = 99999999;
   
    if(PASS_COUNT >= 0)
    {
      BYTE gw = PASS_COUNT % 10; // 个位数
      SHARE = UNIT_MAP;
      CONTROL = NUM_MAP;
      shadowDelay();
    }
    if(PASS_COUNT > 9)
    {
      BYTE sw = PASS_COUNT / 10 % 10; // 十位数
      SHARE = UNIT_MAP;
      CONTROL = NUM_MAP;
      shadowDelay();
    }
    if(PASS_COUNT > 99)
    {
      BYTE bw = PASS_COUNT / 100 % 10; // 百位数
      SHARE = UNIT_MAP;
      CONTROL = NUM_MAP;
      shadowDelay();
    }
    if(PASS_COUNT > 999)
    {
      BYTE qw = PASS_COUNT / 1000 % 10;
      SHARE = UNIT_MAP;
      CONTROL = NUM_MAP;
      shadowDelay();
    }
    if(PASS_COUNT > 9999)
    {
      BYTE ww = PASS_COUNT / 10000 % 10;
      SHARE = UNIT_MAP;
      CONTROL = NUM_MAP;
      shadowDelay();
    }
    if(PASS_COUNT > 99999)
    {
      BYTE sww = PASS_COUNT / 100000 % 10;
      SHARE = UNIT_MAP;
      CONTROL = NUM_MAP;
      shadowDelay();
    }
    if(PASS_COUNT > 999999)
    {
      BYTE bww = PASS_COUNT / 1000000 % 10;
      SHARE = UNIT_MAP;
      CONTROL = NUM_MAP;
      shadowDelay();
    }
    if(PASS_COUNT > 9999999)
    {
      BYTE qww = PASS_COUNT / 10000000 % 10;
      SHARE = UNIT_MAP;
      CONTROL = NUM_MAP;
      shadowDelay();
    }
}
}
内码表:






CListery 发表于 2024-6-28 17:31:22

本帖最后由 CListery 于 2024-7-1 15:23 编辑

第十六集:
1. 定时器的使用场景和使用方式
2. 学习定时器\计数器 T0 的使用
3. 89C52 系列通过 T2 定时器实现刷新数码管
#include <reg52.h>

typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long DWORD;

void delay_ms(BYTE ms)
{
BYTE i;
while(ms--)
{
    for(i=0;i<120;i++);
}
}

void delay_sec(WORD sec)
{
WORD i;
while(sec--)
{
    i = 0;
    while(++i);
}
}

#define SHARE P2

#define CONTROL P0

sbit ADD_TIGGER = P3^0;
sbit SUB_TIGGER = P3^1;
sbit ZERO_TIGGER = P3^2;

BYTE NUM_MAP = {
0x3F, //   0
0x6, //1
0x5B, //   2
0x4F, //   3
0x66, //   4
0x6D, //   5
0x7D, //   6
0x7, //7
0x7F, //   8
0x6F, //   9
};

BYTE UNIT_MAP = {
0x7F,
0xBF,
0xDF,
0xEF,
0xF7,
0xFB,
0xFD,
0xFE,
};

void shadowDelay()
{
delay_ms(1);// 产生残影
}

sfr IPH = 0xB7;
sfr AUXR = 0x8E;

long PASS_COUNT = 0;
void main()
{
      AUXR |= 0x80;                        //定时器时钟1T模式
      TMOD &= 0xF0;                        //设置定时器模式
      TL0 = 0xCD;                              //设置定时初始值
      TH0 = 0xD4;                              //设置定时初始值
      TF0 = 0;                              //清除TF0标志
      TR0 = 1;                              //定时器0开始计时

EA = 1;         // 中断总开关
ET0 = 1;      // T0 中断开关
         
while(1)
{
    if(ADD_TIGGER == 0)
    {
      delay_ms(10);
      if(ADD_TIGGER == 0)
      {
      PASS_COUNT++;
      delay_ms(50);
      }
    }
    else if(SUB_TIGGER == 0)
    {
      delay_ms(10);
      if(SUB_TIGGER == 0)
      {
      PASS_COUNT--;
      delay_ms(50);
      }
    }
    else if(ZERO_TIGGER == 0)
    {
      delay_ms(10);
      while(ZERO_TIGGER == 0)
      PASS_COUNT = 0;
    }
}
}

void Timer0_Isr(void) interrupt 1
{
long TMP = 0;
long complement = 0;

if(PASS_COUNT >= 99999999)
    PASS_COUNT = 99999999;

if(PASS_COUNT < -9999999)
    PASS_COUNT = -9999999;

if(PASS_COUNT < 0)
{
//    complement = ~PASS_COUNT + 1;
//    TMP = (unsigned long)complement;
    TMP = -PASS_COUNT;
   
    SHARE = UNIT_MAP;
    CONTROL = 0x40;
    shadowDelay();
}
else
{
    TMP = PASS_COUNT;
}

if(TMP >= 0)
{
    BYTE gw = TMP % 10; // 个位数
    SHARE = UNIT_MAP;
    CONTROL = NUM_MAP;
    shadowDelay();
}
if(TMP > 9)
{
    BYTE sw = TMP / 10 % 10; // 十位数
    SHARE = UNIT_MAP;
    CONTROL = NUM_MAP;
    shadowDelay();
}
if(TMP > 99)
{
    BYTE bw = TMP / 100 % 10; // 百位数
    SHARE = UNIT_MAP;
    CONTROL = NUM_MAP;
    shadowDelay();
}
if(TMP > 999)
{
    BYTE qw = TMP / 1000 % 10;
    SHARE = UNIT_MAP;
    CONTROL = NUM_MAP;
    shadowDelay();
}
if(TMP > 9999)
{
    BYTE ww = TMP / 10000 % 10;
    SHARE = UNIT_MAP;
    CONTROL = NUM_MAP;
    shadowDelay();
}
if(TMP > 99999)
{
    BYTE sww = TMP / 100000 % 10;
    SHARE = UNIT_MAP;
    CONTROL = NUM_MAP;
    shadowDelay();
}
if(TMP > 999999)
{
    BYTE bww = TMP / 1000000 % 10;
    SHARE = UNIT_MAP;
    CONTROL = NUM_MAP;
    shadowDelay();
}
if(TMP > 9999999)
{
    BYTE qww = TMP / 10000000 % 10;
    SHARE = UNIT_MAP;
    CONTROL = NUM_MAP;
    shadowDelay();
}
}

4. 更新开发板配套代码
#include <STC32G.H>
#include <STC32_STC8_USB.H>
#include "delay_24mhz.h"

char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;

char *USER_STCISPCMD = "@STCISP#";

#define ADD_TIGGER P34
#define SUB_TIGGER P35
#define ZERO_TIGGER P32

long PASS_COUNT = 0;

#define SHARE P7
#define CONTROL P6

BYTE NUM_DATA = {
    0xFF, //
    0xC0, // 0
    0xF9, // 1
    0xA4, // 2
    0xB0, // 3
    0x99, // 4
    0x92, // 5
    0x82, // 6
    0xF8, // 7
    0x80, // 8
    0x90// 9
};

BYTE UNIT_MAP = {
    0xFE, //
    0xFD, //
    0xFB, //
    0xF7, //
    0xEF, //
    0xDF, //
    0xBF, //
    0x7F//
};

BYTE DATA = {
    0xFF,
    0xFF,
    0xFF,
    0xFF,
    0xFF,
    0xFF,
    0xFF,
    0xFF,
};

void sys_init()
{
WTST = 0;
EAXFR = 1;
CKCON = 0;
}

void set_interrupt()
{
AUXR &= 0x7F; // 设置T0为12T模式,即12分频
TMOD &= 0xF0; // 设置T0为16位自动重载定时器模式且无需上拉 INT0 引脚

// 设置定时 1ms
TL0 = 0x30; // 定时器T0设置低八位起始值
TH0 = 0xF8; // 定时器T0设置高八位起始值

TF0 = 0; // T0 溢出标志
TR0 = 1; // T0 运行控制位

ET0 = 1; // T0 开关
EA = 1;// 中断总开关
}

long TMP = 0;
BYTE pos = 0;
BYTE unit = 0;
unsigned long pow = 0;

void main()
{
sys_init();
usb_init();

set_interrupt();

P7M0 = 0;
P7M1 = 0;
P6M0 = 0;
P6M1 = 0;
P3M0 = 0x00;
P3M1 = 0x00;

P3PU |= 0x30;

while (1)
{
    if (ADD_TIGGER == 0)
    {
      delay_ms(10);
      if (ADD_TIGGER == 0)
      {
      PASS_COUNT++;
      delay_ms(10);
      }
    }
    else if (SUB_TIGGER == 0)
    {
      delay_ms(10);
      if (SUB_TIGGER == 0)
      {
      PASS_COUNT--;
      delay_ms(10);
      }
    }
    else if (ZERO_TIGGER == 0)
    {
      delay_ms(10);
      while (ZERO_TIGGER == 0)
      ;
      PASS_COUNT = 0;
    }

    if (PASS_COUNT >= 99999999)
      PASS_COUNT = 99999999;

    if (PASS_COUNT < -9999999)
      PASS_COUNT = -9999999;

    TMP = PASS_COUNT < 0 ? -PASS_COUNT : PASS_COUNT;

    for (pos = 0; pos < 8; pos++)
    {
      pow = pos > 0 ? 10 : 1;
      for (unit = 1; unit < pos; unit++)
      {
      pow *= 10;
      }
      if (pos == 7)
      {
      if (PASS_COUNT < 0)
      {
          DATA = 0xBF;
          continue;
      }
      }
      DATA = NUM_DATA[(TMP / pow) % 10+ (TMP > (pow - 1) ? 1 : 0)];
    }
}
}

BYTE index = 0;

void T0_run(void) interrupt 1
{
SHARE = UNIT_MAP;
CONTROL = DATA;
index++;
if (index > 7)
{
    index = 0;
}
}





CListery 发表于 2024-6-29 18:22:26

本帖最后由 CListery 于 2024-7-1 15:45 编辑

第十七课:
1. 学习 T1 计数器的使用
2. 学习 IO 口内部上拉设置
3. 89C52 单片机使用 T1 计数器反转 LED
#include <reg52.h>

sbit LED = P1^0;

void main()
{
//      AUXR &= 0xBF;                        //定时器时钟12T模式
      TMOD &= 0x0F;                        //设置定时器模式
TMOD = 0x40;

      TL1 = 0xFF;                              //设置定时初始值
      TH1 = 0xFF;                              //设置定时初始值

      TF1 = 0;                              //清除TF1标志
      TR1 = 1;                              //定时器1开始计时

      ET1 = 1;                              //使能定时器1中断
EA = 1;

while(1);
}

void Timer1_Isr(void) interrupt 3
{
      TL1 = 0xFF;                              //设置定时初始值
      TH1 = 0xFF;                              //设置定时初始值

LED = !LED;

}
4. 更新开发板代码
#include <STC32G.H>
#include <STC32_STC8_USB.H>

char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;

char *USER_STCISPCMD = "@STCISP#";

#define LED P67

void sys_init()
{
WTST = 0;
EAXFR = 1;
CKCON = 0;
}

void set_interrupt()
{
AUXR = 0x40; // 设置T1为1T模式,即不分频
TMOD = 0x40; // 设置T1为16位自动重载计数器模式且无需上拉 INT1 引脚

// 设置外部 P3.5 拉低一次触发一次中断
TL1 = 0xFF; // 计数器T1设置低八位起始值
TH1 = 0xFF; // 计数器T1设置高八位起始值

TF1 = 0; // T1 溢出标志
TR1 = 1; // T1 运行控制位

ET1 = 1; // T1 开关
EA = 1;// 中断总开关
}

void main()
{
sys_init();
usb_init();

set_interrupt();

P4M0 = 0;
P4M1 = 0;
P6M0 = 0;
P6M1 = 0;

P3PU |= 0x30;

P40 = 0;

while (1)
    ;
}

void T1_run(void) interrupt 3
{
LED = !LED;
}






soma 发表于 2024-6-29 20:24:45

TL1 = 0xFF;TH1 = 0xFF;这个是定时器t1最大值,加1就溢出。这样led效果是常亮吧,且亮度不是很大。

CListery 发表于 2024-6-30 19:43:54

soma 发表于 2024-6-29 20:24
TL1 = 0xFF;TH1 = 0xFF;这个是定时器t1最大值,加1就溢出。这样led效果是常亮吧,且亮度不是很大。 ...

最大值是65536溢出,我设定的初始值是65535,所以只要按一次外部计时器对应的按键就会触发一次计数器中断,然后就会重置 TL1 和 TH1 然后反转 LED 的高低电平
页: 1 [2] 3 4
查看完整版本: 跟着冲哥学习单片机