noonezero 发表于 2023-9-7 11:43:00

本帖最后由 noonezero 于 2023-9-10 07:54 编辑

第九课:数码管的静态使用


1.显示一个数字







数码管显示





代码 我增加了sizeof函数,这样想显示什么,直接在数组上加,不用修改后面的代码


#include <STC32G.H>
#include "../COMM/stc32_stc8_usb.h"

#define KEY1 P32// 功能按键一
#define KEY2 P33// 功能按键二

#define BEEP P54   // 蜂鸣器引脚,低电平响

void sys_init();
//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";                      //设置自动复位到ISP区的用户接口命令

void Delay_ms(int x)      //@24.000MHz
{
        unsigned long edata i;
        for(; x > 0; x--)
        {
        _nop_();
        _nop_();
        _nop_();
        i = 5998UL;
                while (i) i--;
        }
}



void main()
{
       
        u8 SEG_Tab[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x89, 0xC7, 0xA3, 0x8C, 0xC1};// 这里不写多少也行,会算出来
        u8 num = 0;// 显示数组中第几个字符
       
        sys_init();
        usb_init();//USB初始化
        EA = 1;
       
        P70 = 0;// 开启数码管
    while(1)
    {
      P6 = SEG_Tab;// 显示第几个
      
      if(KEY1 == 0)
      {
            Delay_ms(10);// 软件消抖
            if(KEY1 == 0)
            {
                BEEP = 0;      // 打开蜂鸣器
                Delay_ms(10);// 延时
                BEEP = 1;      // 关闭蜂鸣器
                while(KEY1 == 0);// 死循环 等待抬起
                if(num < sizeof(SEG_Tab) / sizeof(SEG_Tab))// 算出数组长度
                {
                  num ++;
                }
            }
      }
      if(KEY2 == 0)
      {
            Delay_ms(10);// 软件消抖
            if(KEY2 == 0)
            {
                BEEP = 0;      // 打开蜂鸣器
                Delay_ms(10);// 延时
                BEEP = 1;      // 关闭蜂鸣器
                while(KEY2 == 0);// 死循环 等待抬起
                if(num > 0)
                {
                  num --;
                }
            }
      }
    }
}


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

    P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P1M1 = 0x32;   P1M0 = 0x32;   //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
    P2M1 = 0x3c;   P2M0 = 0x3c;   //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
    P3M1 = 0x50;   P3M0 = 0x50;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
    P4M1 = 0x3c;   P4M0 = 0x3c;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P5M1 = 0x0c;   P5M0 = 0x0c;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
    P6M1 = 0xff;   P6M0 = 0xff;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
}





noonezero 发表于 2023-9-8 10:18:27

本帖最后由 noonezero 于 2023-9-10 09:17 编辑

第十课:数码管的动态显示

动态点亮八个数码管控制原理




P7 开关显示对应数码管对应的值



作业代码


#include <STC32G.H>
#include <intrins.h>
#include "../COMM/stc32_stc8_usb.h"

#define KEY1 P32// 功能按键一
#define KEY2 P33// 功能按键二

#define BEEP P54// 蜂鸣器引脚,低电平响

u8 SEG_Tab[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0xBF
};// 这里不写多少也行,会算出来
bit onoroff = 0;// 开机还是关机
u32 count = 18456000;


//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";                      //设置自动复位到ISP区的用户接口命令
void sys_init();


void Delay_ms(int x)      //@24.000MHz
{
      unsigned long edata i;
      for(; x > 0; x--)
      {
      _nop_();
      _nop_();
      _nop_();
      i = 5998UL;
                while (i) i--;
      }
}

void show(u8 P7index, u8 showtabindex)// P7index 从1开始
{
    u8 indexnum = 0x01;
      P6 = 0xFF;
    P7 = ~(indexnum << (8 - P7index));
    P6 = SEG_Tab;
    Delay_ms(1);
}

void showinit()
{
    show(1, 0);
    show(2, 0);
    show(3, 10);
    show(4, 0);
    show(5, 0);
    show(6, 10);
    show(7, 0);
    show(8, 0);
}

void countshow()// count计数显示
{
    u32 a = count / 100;// 显示延时了好多,这里如果按1000算 太慢了,100差不多
      int mouth =a/(60 * 60);// 求小时
      int min =(a - mouth * (60 * 60)) / 60;// 求分
      int s = a - mouth * (60 * 60) - min * 60;// 求秒
    show(1, (u8)mouth/10);
    show(2, (u8)mouth%10);
    show(3, 10);
   
    show(4, (u8)min/10);
    show(5, (u8)min%10);
    show(6, 10);
   
    show(7, (u8)s/10);
    show(8, (u8)s%10);
}

void main()
{
      sys_init();
      usb_init();//USB初始化
      EA = 1;
      
      while(1)
    {
                if(onoroff)
      {
            count++;
            countshow();
      }
                else
                {
                        showinit();
                }
                Delay_ms(1);// 延时
   
      if(KEY1 == 0)
      {
            Delay_ms(10);// 软件消抖
            if(KEY1 == 0)
            {
                BEEP = 0;      // 打开蜂鸣器
                Delay_ms(10);// 延时
                BEEP = 1;      // 关闭蜂鸣器
                while(KEY1 == 0)// 死循环 等待抬起
                {
                  showinit();
                }
                onoroff = !onoroff;
                count = 0;
            }
      }
    }

}


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

    P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P1M1 = 0x32;   P1M0 = 0x32;   //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
    P2M1 = 0x3c;   P2M0 = 0x3c;   //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
    P3M1 = 0x50;   P3M0 = 0x50;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
    P4M1 = 0x3c;   P4M0 = 0x3c;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P5M1 = 0x0c;   P5M0 = 0x0c;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
    P6M1 = 0xff;   P6M0 = 0xff;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
}











noonezero 发表于 2023-9-11 08:53:18

本帖最后由 noonezero 于 2023-9-13 13:48 编辑

第十一课:定时器的使用


定时器使用比前十节的视频难度蹭的就上来了

之前的就是简单的I/O操作,配置好模式就只剩下设置高低电平了
定时器这节,刷了几个视频才对定时器,中断有些了解了


简单说,定时器就是按系统时钟,分频下 然后计数脉冲。脉冲计数达到65536 时溢出,产生中断。
计数初始值可以通过 TH0 和 TL0 配置





以下代码通过定时器改了上节课的代码


#include <STC32G.H>
#include <intrins.h>
#include "../COMM/stc32_stc8_usb.h"

#define KEY1 P32// 功能按键一
#define KEY2 P33// 功能按键二

#define BEEP P54// 蜂鸣器引脚,低电平响

u8 SEG_Tab[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0xBF
};// 这里不写多少也行,会算出来
bit onoroff = 0;// 开机还是关机
u32 count = 18456000;


//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";                      //设置自动复位到ISP区的用户接口命令
void sys_init();


void Delay_ms(int x)      //@24.000MHz
{
      unsigned long edata i;
      for(; x > 0; x--)
      {
      _nop_();
      _nop_();
      _nop_();
      i = 5998UL;
                while (i) i--;
      }
}

void show(u8 P7index, u8 showtabindex)// P7index 从1开始
{
    u8 indexnum = 0x01;
      P6 = 0xFF;
    P7 = ~(indexnum << (8 - P7index));
    P6 = SEG_Tab;
    Delay_ms(1);
}

void showinit()
{
    show(1, 0);
    show(2, 0);
    show(3, 10);
    show(4, 0);
    show(5, 0);
    show(6, 10);
    show(7, 0);
    show(8, 0);
}

void countshow()// count计数显示
{
    u32 a = count / 1000;// 显示延时了好多,这里如果按1000算 太慢了,100差不多
      int mouth =a/(60 * 60);// 求小时
      int min =(a - mouth * (60 * 60)) / 60;// 求分
      int s = a - mouth * (60 * 60) - min * 60;// 求秒
    show(1, (u8)mouth/10);
    show(2, (u8)mouth%10);
    show(3, 10);
   
    show(4, (u8)min/10);
    show(5, (u8)min%10);
    show(6, 10);
   
    show(7, (u8)s/10);
    show(8, (u8)s%10);
}

void main()
{
      sys_init();
      usb_init();//USB初始化
      EA = 1;
      
      /**定时器配置**/
      AUXR &= 0x7F;//定时器时钟12T模式
      TMOD &= 0xF0;//设置定时器模式
      TH0 = 0xF8;// 计算出24M时钟下1ms定时时间初始值
      TL0 = 0x30;
      TR0 = 1;// 启动定时器
      EA = 1;// 打开总中断
      ET0 = 1;// 使能定时器中断
      
      while(1)
    {
                if(onoroff)
      {
            countshow();
      }
                else
                {
                        showinit();
                }
   
      if(KEY1 == 0)
      {
            Delay_ms(10);// 软件消抖
            if(KEY1 == 0)
            {
                BEEP = 0;      // 打开蜂鸣器
                Delay_ms(10);// 延时
                BEEP = 1;      // 关闭蜂鸣器
                while(KEY1 == 0)// 死循环 等待抬起
                {
                  showinit();
                }
                onoroff = !onoroff;
                count = 0;
            }
      }
    }

}

void Timer0_Isr(void) interrupt 1
{
      count++;
}


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

    P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P1M1 = 0x32;   P1M0 = 0x32;   //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
    P2M1 = 0x3c;   P2M0 = 0x3c;   //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
    P3M1 = 0x50;   P3M0 = 0x50;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
    P4M1 = 0x3c;   P4M0 = 0x3c;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P5M1 = 0x0c;   P5M0 = 0x0c;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
    P6M1 = 0xff;   P6M0 = 0xff;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
}



noonezero 发表于 2023-9-14 12:07:49

第十二课:计数器的使用


1.开启内部上拉电阻




2.补充中断号





代码
冲哥代码中 TF1 位不用清零,默认就是0,响应中断后会硬件清零
#include <STC32G.H>
#include <intrins.h>
#include "../COMM/stc32_stc8_usb.h"


//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";                      //设置自动复位到ISP区的用户接口命令
void sys_init();


void Delay_ms(int x)      //@24.000MHz
{
        unsigned long edata i;
        for(; x > 0; x--)
        {
        _nop_();
        _nop_();
        _nop_();
        i = 5998UL;
                while (i) i--;
        }
}

void main()
{
        sys_init();
        usb_init();//USB初始化
       
        P40 = 0;
        P3PU = 0x20;// 启动P35上拉电阻
       
        /**定时器配置**/
        TMOD |= 0x40;//设置定时器0计数模式
        TH1 = 0xFF;// 计算出24M时钟下1ms定时时间初始值
        TL1 = 0xFF;
        TR1 = 1;// 启动计数器
        EA = 1;// 打开总中断
        ET1 = 1;// 使能定时器中断
       
       
        while(1)
    {
                ;
    }

}

void Timer1_Isr(void) interrupt 3
{
        P6 = ~P6;
}


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

    P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P1M1 = 0x32;   P1M0 = 0x32;   //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
    P2M1 = 0x3c;   P2M0 = 0x3c;   //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
    P3M1 = 0x50;   P3M0 = 0x50;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
    P4M1 = 0x3c;   P4M0 = 0x3c;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P5M1 = 0x0c;   P5M0 = 0x0c;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
    P6M1 = 0xff;   P6M0 = 0xff;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
}


noonezero 发表于 2023-9-14 21:56:46

本帖最后由 noonezero 于 2023-9-24 15:13 编辑

第十三课:简单多任务处理


1.创建程序文件

[*]新建文件并添加到工程
[*]添加引用路径



引脚定义在.h文件中
sbit 名称 = P10;
#define 名称 P10


2.修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”
extern修饰的变量不能赋初值


3.bdata位寻址变量的使用




4.代码待填



noonezero 发表于 2023-9-24 18:43:38

本帖最后由 noonezero 于 2023-9-25 14:22 编辑

第十四课:什么是矩阵按键


1.原理图




2.实现原理
端口默认高电平,实时读取引脚为低电平表示按下


1. 将P00-P03输出低电平,P06-P07输出高电平,如果有按键按下,按下的那一列IO就会变成低电平,可以判断哪一列按下了


2. 将P00-P03输出高电平,P06-P07输出低电平,如果有按键按下,按下的那一列IO就会变成低电平,可以判断哪一列按下了


3. 行列组合就能知道是哪个按键按下了



3.实现代码:


#include <STC32G.H>
#include "../COMM/stc32_stc8_usb.h"

void sys_init();

//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";                      //设置自动复位到ISP区的用户接口命令


/*
函数功能:定时器0定时初始化
入口参数:@
函数返回:
其他备注:

*/
void Timer0init()
{
        AUXR &= 0x7F;//定时器时钟12T模式 默认就是
        TMOD &= 0xF0;//设置定时器模式
        TH0 = 0xF8;// 计算出24M时钟下1ms定时时间初始值
        TL0 = 0x30;
        ET0 = 1;// 使能定时器中断
        TR0 = 1;   // 开始定时
}


void Delay_ms(int x)      //@24.000MHz
{
        unsigned long edata i;
        for(; x > 0; x--)
        {
                _nop_();
                _nop_();
                _nop_();
                i = 5998UL;
                while (i) i--;
        }
}

// 矩阵按键
u8 MateixKEY_Read()
{
        u8 keystate; u8 key_val;
        // 端口默认高电平,实时读取引脚为低电平表示按下
        // 1. 将P00-P03输出低电平,P06-P07输出高电平,如果有按键按下,按下的那一列IO就会变成低电平,可以判断哪一列按下了
        P0 = 0xC0;                        // 1100 0000
        Delay_ms(10);
        keystate = (P0 ^ 0xC0);        // 0100 0000 ^ 1100 0000 = 1000 0000 假设第7位按下
       
        // 2. 将P00-P03输出高电平,P06-P07输出低电平,如果有按键按下,按下的那一列IO就会变成低电平,可以判断哪一列按下了
        P0 = 0x0F;                        // 1100 0000
        Delay_ms(10);
        keystate |= (P0 ^ 0x0F);

        switch (keystate)
    {
            case 0x41: key_val = 1;
                    break;
            case 0x42: key_val = 2;
                    break;
                case 0x44: key_val = 3;
                    break;
            case 0x48: key_val = 4;
                    break;
                case 0x81: key_val = 5;
                    break;
            case 0x82: key_val = 6;
                    break;
                case 0x84: key_val = 7;
                    break;
            case 0x88: key_val = 8;
                    break;
            default: key_val = 0;
                    break;
    }
        return key_val;
       
}

u8 SEG_Tab = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x89, 0xC7, 0xA3, 0x8C, 0xC1};// 这里不写多少也行,会算出来

void main()
{
        //
        u8 num = 0;// 显示数组中第几个字符
       
        sys_init();
        usb_init();//USB初始化
       
        //Timer0init();
        EA = 1;
       
       
       
        P40 = 0;
        P70 = 0;
        P6 = 0;
       
        while(1)
        {
                num = MateixKEY_Read();
                P6 = SEG_Tab;
        }
}

/*
函数功能:定时器0中断执行函数
入口参数:@
函数返回:
其他备注:
*/
void Timer0_Isr(void) interrupt 1
{
       
}


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

    P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P1M1 = 0x32;   P1M0 = 0x32;   //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
    P2M1 = 0x3c;   P2M0 = 0x3c;   //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
    P3M1 = 0x50;   P3M0 = 0x50;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
    P4M1 = 0x3c;   P4M0 = 0x3c;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P5M1 = 0x0c;   P5M0 = 0x0c;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
    P6M1 = 0xff;   P6M0 = 0xff;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
}




noonezero 发表于 2023-9-26 18:43:24

本帖最后由 noonezero 于 2023-9-27 07:46 编辑

第十五课:外部中断


1.什么是中断



中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的。
当CPU正在处理某件事的时候外界发生了紧急事件请求,要求CPU暂停当前的工作,转而去处理这个紧急事件,处理完以后再回到原来被中断的地方,继续原来的工作,这样的过程就叫中断。


2.中断的嵌套
正在执行中断的时候发生优先级更高的中断,会先去执行优先级高的


3.中断结构图




4.什么是外部中断
在单片机引脚上,由于外部因素导致一个电平的变化,跳变。而通过捕获这个变化,单片机内部自主运行的程序就会被暂时打断,转而去执行相应的中断处理程序,执行完后又回到原来中断的地方继续原来的程序


5.程序代码
#include <STC32G.H>
#include "../COMM/stc32_stc8_usb.h"

void sys_init();

//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";                      //设置自动复位到ISP区的用户接口命令



void Delay_ms(int x)      //@24.000MHz
{
      unsigned long edata i;
      for(; x > 0; x--)
      {
                _nop_();
                _nop_();
                _nop_();
                i = 5998UL;
                while (i) i--;
      }
}


void main()
{
      //
      u8 num = 0;// 显示数组中第几个字符
      
      sys_init();
      usb_init();//USB初始化
      EA = 1;
      
      IT1 = 1;                        // 使能INT1下降沿中断
      EX1 = 1;                        // 使能INT1中断
      
      P40 = 0;
      P70 = 0;
      P6 = 0;
      
      while(1)
      {

      }
}



void Timer1_Isr(void) interrupt 2   // 外部中断1中断函数
{
      P6 = ~P6;
}


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

    P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P1M1 = 0x32;   P1M0 = 0x32;   //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
    P2M1 = 0x3c;   P2M0 = 0x3c;   //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
    P3M1 = 0x50;   P3M0 = 0x50;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
    P4M1 = 0x3c;   P4M0 = 0x3c;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P5M1 = 0x0c;   P5M0 = 0x0c;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
    P6M1 = 0xff;   P6M0 = 0xff;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
}

问题,我用外部中断0,上下沿和下降沿都可以正常亮灭灯,但是用定时器1就不行,即使配置的是下降沿,上升沿的时候灯依旧会取反一次,我看原理图中有上拉电阻,不清楚原因,先略过,以后解答



noonezero 发表于 2023-9-27 09:54:44

本帖最后由 noonezero 于 2023-10-1 14:47 编辑

第十六课:IO中断


1.什么是IO中断
STC32G系列支持所有的I/O中断,且支持4种中断模式,下降沿中断,上升沿中断,低电平中断,高电平中断。每组IO口均有独立的中断入口地址,且每个IO可独立设置中断模式

2.寄存器相关配置
01使能寄存器配置




02中断标志寄存器




03中断模式配置寄存器




04优先级控制寄存器



2.IO中断的用法
由于中断号大于31,keil不能直接编译,需要下载软件拓展中断号,下载地址深圳国芯人工智能有限公司-工具软件 (stcai.com)


3.中断优先级设置


4.中断代码
#include <STC32G.H>
#include "../COMM/stc32_stc8_usb.h"

void sys_init();

//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";                      //设置自动复位到ISP区的用户接口命令



void Delay_ms(int x)      //@24.000MHz
{
        unsigned long edata i;
        for(; x > 0; x--)
        {
                _nop_();
                _nop_();
                _nop_();
                i = 5998UL;
                while (i) i--;
        }
}


void main()
{
        sys_init();
        usb_init();//USB初始化
        EA = 1;
       
        // P3IO中断配置 下降沿中断
        P3IM0 = 0x00;
        P3IM1 = 0x00;
        P3INTE = 0x20;// 使能P35中断 0010 0000
        //P35INTE = 0;// 这种方式不能用
       
        P40 = 0;
        P70 = 0;
        P6 = 0;
       
        while(1)
        {

        }
}



void P3Exit_Isr(void) interrupt 40   // 外部中断1中断函数
{
        u8 intf;
       
        intf = P3INTF;
        if(intf)
        {
                P3INTF = 0x00;
                if(intf & 0x20)
                {
                        P6 = ~P6;
                }
        }
}


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

    P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P1M1 = 0x32;   P1M0 = 0x32;   //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
    P2M1 = 0x3c;   P2M0 = 0x3c;   //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
    P3M1 = 0x50;   P3M0 = 0x50;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
    P4M1 = 0x3c;   P4M0 = 0x3c;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P5M1 = 0x0c;   P5M0 = 0x0c;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
    P6M1 = 0xff;   P6M0 = 0xff;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
}







noonezero 发表于 2023-10-2 12:43:48

本帖最后由 noonezero 于 2023-10-4 17:33 编辑

第十七课:模数转换器ADC


1.模数转换器是什么

模数转换器即A/D转换器,简称ADC,通常是指一个将模拟信号转变为数字信号的电子元器件


模拟信号 -> 电压
数字信号 -> 0/1组成的二进制数


如果芯片有ADC的外部参考电源管脚 ADC_VRef+, 则一定不能浮空,必须接外部参考电源或者直接连到VCC。


2.需要配置的寄存器



ADC_POWER:ADC电源控制位,0关闭ADC,1打开。建议进入空闲模式和掉电模式前将ADC电源关闭,以降低功耗;
                      1. 给MCU的内部ADC模块电源打开后,需等待约1ms,等MCU内部的ADC电源稳定后再让ADC工作。
                      2.适当加长对外部信号的采样时间,就是对ADC内部采样保持电容的充电放电时间,时间够,内部才能和外部电势相等。



ADC_START:开始转换,转换后自动清0,手动输0不会停止转换
ADC_FLAG:转换结束标志位,转换完成会置1,需要软件清零
ADC_EPWMP:暂空,需要PWM
ADC_CHS:通道选择位,选择好通道需要把对应IO口设置为高阻输入


RESFMT:0转换结果左对齐,1右对齐
SPEED:设置ADC时钟


ADC_RES:转换结果高位
ADC_RESL:转换结果低位


3.ADC速度计算公式



4.ADC转换结果公式



5.反推ADC输入电压计算公式



5.反推工作电压计算公式



6.代码-查询方式

#include "config.h"
#include <STC32G.H>
#include "../COMM/stc32_stc8_usb.h"
#include "stdio.h"

void sys_init();

//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";


// ADC初始化
void ADC_init()
{
        //P10高祖输入
        P0M1 &= 0xFE;
        P0M1 |= 0x01;
       
        ADCTIM = 0x3F;        // 设置ADC内部时序
        ADCCFG = 0x2F;        // 数据右对齐,方便合二为一。时钟选择为最慢
        ADC_POWER = 1;        // 打开ADC电源
}

// ADC读取
u16 ADC_Read(u8 num)
{
        u16 adcval;                                // ADC数值保存变量
        ADC_CONTR &= 0xF0;                // 清空通道
        ADC_CONTR |= num;                // 选择通道
        ADC_START = 1;                        // 开启ADC转化
        _nop_();                                // 空操作指令
        _nop_();
        while(!ADC_FLAG);                // 等待ADC转换结束
        ADC_FLAG = 0;                        // 手动清零
        adcval = (ADC_RES << 8) + ADC_RESL;        // 计算ADC数值
       
        return adcval;
       
}

void main()
{
        u16 ADC_VAL;
        sys_init();
        usb_init();//USB初始化
        EA = 1;
       
        ADC_init();
       
        while(1)
        {
                if (bUsbOutReady)
      {
            USB_SendData(UsbOutBuffer, 64);
            usb_OUT_done();
                }
                ADC_VAL = ADC_Read(0);
                printf("adcvalue\t%d\r\n",(int)ADC_VAL);
//                printf("wenjun\r\n");

        }
}

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

    P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P1M1 = 0x32;   P1M0 = 0x32;   //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
    P2M1 = 0x3c;   P2M0 = 0x3c;   //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
    P3M1 = 0x50;   P3M0 = 0x50;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
    P4M1 = 0x3c;   P4M0 = 0x3c;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P5M1 = 0x0c;   P5M0 = 0x0c;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
    P6M1 = 0xff;   P6M0 = 0xff;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
}


noonezero 发表于 2023-10-5 15:24:12

第十八课:ADC采集电源电压和ADC按键


1.ADC采集电源电压

内部1.19V电源有+-1%误差,可以利用ADC的第15通道反推ADC_VRef+脚外接参考电源电压






#include "config.h"
#include <STC32G.H>
#include "../COMM/stc32_stc8_usb.h"
#include "stdio.h"

#define                VREFH_ADDR                CHIPID7
#define                VREFL_ADDR                CHIPID8

int BGV;

void sys_init();

//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";


// ADC初始化
void ADC_init()
{
        ADCTIM = 0x3F;        // 设置ADC内部时序
        ADCCFG = 0x2F;        // 数据右对齐,方便合二为一。时钟选择为最慢
        ADC_CONTR = 0x8F;                // 选择通道15
}

// ADC读取
int ADC_Read()
{
        int res;                                // ADC数值保存变量
       
        ADC_START = 1;                        // 开启ADC转化
        _nop_();                                // 空操作指令
        _nop_();
        while(!ADC_FLAG);                // 等待ADC转换结束
        ADC_FLAG = 0;                        // 手动清零
        res = (ADC_RES << 8) | ADC_RESL;        // 计算ADC数值
       
        return res;
}

void main()
{
        int res;
        int vcc;
        int i;
        sys_init();
        usb_init();//USB初始化
        EA = 1;
       
        BGV = (VREFH_ADDR << 8) + VREFL_ADDR;                // 从CHIPID中读取内部参考电压值
       
        ADC_init();
        ADC_Read();
        ADC_Read();
        ADC_Read();
        ADC_Read();                // 舍弃四个值
       
        res = 0;
        for(i=0; i<8; i++)
        {
                res += ADC_Read();
        }
        res >>= 3;// res / 8 算平均值
        vcc = (int)(4096L * BGV / res);
       
        while(1)
        {
                if (bUsbOutReady)
      {
            USB_SendData(UsbOutBuffer, 64);
            usb_OUT_done();
                }
                printf("power \t%d\r\n", vcc);

        }
}

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

    P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P1M1 = 0x32;   P1M0 = 0x32;   //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
    P2M1 = 0x3c;   P2M0 = 0x3c;   //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
    P3M1 = 0x50;   P3M0 = 0x50;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
    P4M1 = 0x3c;   P4M0 = 0x3c;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P5M1 = 0x0c;   P5M0 = 0x0c;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
    P6M1 = 0xff;   P6M0 = 0xff;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
}





ADC按键,后面补,我的实验箱有点BUG,按键1-5可以用,其他都不行。
页: 1 [2] 3 4
查看完整版本: 冲哥STC32G单片机学习笔记