找回密码
 立即注册
楼主: 未元星系

8H8K64U开天斧开发板学习笔记

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:443
  • 最近打卡:2025-05-09 10:10:53
已绑定手机

31

主题

142

回帖

1619

积分

金牌会员

积分
1619
发表于 2024-5-27 22:57:59 | 显示全部楼层
本帖最后由 未元星系 于 2024-5-27 22:59 编辑

自学开天斧第⑤课:
学习内容:1、外部中断
学习简介:STC8H8K64U单片机内置五个外部中断,INT0,INT1,INT2,INT3,INT4;分别对应引脚:P3.2,P3.3,P3.6,P3.7,P3.0;分别对应中断号:interrupt 0,2,10,11,16;

其中INT0和INT1即支持上升沿/下降沿中断(同时支持两种方式引发中断),也支持下降沿中断,INT2,INT3,INT4只支持下降沿中断。
外部INT0,INT1所连引脚正好为两个独立按键,本次实验:主函数执行死循环,设INT0,INT1为下降沿触发,若P3.3按键按下,LED交替闪烁两回合;若P3.2按下,LED闪烁两次
程序代码:

#define MAIN_Fosc                24000000L        
void Delay_ms(unsigned int ms)
{
        unsigned int i;
        do{
                i = MAIN_Fosc / 10000;
                while(--i);
        }while(--ms);
}

void main()
{
        
        P2M0 = 0x00; P2M1 = 0x00;   //P2口设为准双向口模式
        P3M0 = 0x00; P3M1 = 0x00;   //P3口设为准双向口模式
  P2 = 0xff;                  //熄灭全部LED
        P2 |= 0x30;                 //P3.2, P3.3口设为高电平
        
        IT0 = 1;                    //外部中断0设置为下降沿触发(若IT0=1则设置为上升沿+下降沿触发)
        EX0 = 1;                    //使能INT0
        IT1 = 1;                    //外部中断1设置为下降沿触发(若IT1=1则设置为上升沿+下降沿触发)
        EX1 = 1;                    //使能INT1
        
        EA = 1;                                  //打开总中断
        
        while(1){}                  //死循环
}

void INT0_Routine(void)  interrupt 0
{
    P2 = 0x55;Delay_ms(150);
    P2 = 0xAA;Delay_ms(150);
    P2 = 0x55;Delay_ms(150);
    P2 = 0xAA;Delay_ms(150);
    P2 = 0xff;
}

void INT1_Routine(void)  interrupt 2
{
   P2 = 0x00;Delay_ms(100);
   P2 = 0xff;Delay_ms(100);
   P2 = 0x00;Delay_ms(100);
   P2 = 0xff;Delay_ms(100);
}


代码现象:P3.3按键按下,LED交替闪烁两回合;P3.2按下,LED闪烁两次
存在问题:按键按下会产生抖动,目前外部中断里的消抖本人目前也没完全弄明白,所以此程序可能会导致按一下按键触发多次中断的现象。

中断(1).png
中断(3).png
中断(2).png

外部中断.mp4

2.22 MB, 下载次数: 166

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:443
  • 最近打卡:2025-05-09 10:10:53
已绑定手机

31

主题

142

回帖

1619

积分

金牌会员

积分
1619
发表于 2024-5-28 23:23:29 | 显示全部楼层
本帖最后由 未元星系 于 2024-5-28 23:26 编辑

自学开天斧第⑥课:
学习内容:1、定时器延时
学习简介:前期我学习的延时函数是严重占用单片机进程的,实际编程中不是十分提倡,今天开始学习定时器延时。
实验内容:用定时器0进行延时,流水灯
程序代码:
bit bit_1ms;
unsigned int delay;

void Timer0_Init(void)  //定时1ms
{
        AUXR |= 0x80;  //设置定时器为1T模式,即不分频
        TMOD &= 0xF0;  //保留高四位(定时器1),低四位全为0:设置定时器/计数器0为定时器、GATE置0、16位自动重装模式
        TL0 = 0x3F;           //初始值65535 - 24000 = 41535 = 1010 0010 0011 1111,即高8位为0xA2,低8位为0x3F
        TH0 = 0xA2;           //
        TF0 = 0;                    //清零TF0中断标志位
        TR0 = 1;                    //定时器开始计时
        ET0 = 1;       //开启定时器0中断
}

void main()
{
        P2M0 = 0x00; P2M1 = 0x00;   //P2口设为准双向口模式
       Timer0_Init();
       EA = 1;                                  //打开总中断

        while(1)
        {
                static unsigned char j;
                if(bit_1ms == 1)
                {
                        bit_1ms = 0;
                        delay++;
                }
                if(delay >= 100)  //流水灯流动速度:100ms
                {
                        delay = 0;
                        P2 = ~(0x01 << j);
                        j ++ ;
                        if(j > 7){j = 0;}
               }
               
       }                 
}

void Timer0_Routine(void) interrupt 1   //定时器0中断
{
        bit_1ms = 1;  //设置标志位,bit_1ms清零后置1说明时间过了1ms
}

代码现象:循环流水灯,速度100ms
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:443
  • 最近打卡:2025-05-09 10:10:53
已绑定手机

31

主题

142

回帖

1619

积分

金牌会员

积分
1619
发表于 2024-5-31 22:08:13 | 显示全部楼层
本帖最后由 未元星系 于 2024-5-31 23:11 编辑

自学开天斧第⑦课:
学习内容:1、串口通信
学习简介:STC8H8K64U单片机有四个串口,都为全双工异步串行通信接口,串口1有四种工作模式,串口2、3、4有两种(本次学习串口1的模式1),串口1可切换4组引脚,串口2、3、4能切换2组
实验项目:1.单片机向电脑发送数据:开天斧4个板载按键,按下分别向电脑发送 “你好呀!”  “很高兴认识你!”  “祝你好运!”  “再见!”
                2.电脑向单片机发送数据:STC-ISP串口助手向单片机发送16进制数,8个板载LED按照2进制点亮(注意将串口发送调为HEX模式)
程序代码:
#define MAIN_Fosc     24000000L
sbit KEY1 = P3^2; sbit KEY2 = P3^3; sbit KEY3 = P3^4; sbit KEY4 = P3^5;        // 板载的4个按键
bit B_1ms;           // 1毫秒标志
bit key1flag; bit key2flag; bit key3flag; bit key4flag;         // 按键1按下标志
bit blinkflag;                        // 闪烁标志
bit busy;     //忙状态
char key1delay;        char key2delay;        char key3delay;        char key4delay;            // 4个按键计时

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

void Uart1Init()                                                        // UART1初始化
{
        P_SW1 &= 0x3F;              //设置串口1引脚为P3.0,P3.1
        SCON = 0x50;                                                                // 模式1(8位数据)、接收使能
        PCON |= 0x00;               //设置波特率不加倍,关闭帧错检测功能
        T2L = BRT;                                                
        T2H = BRT >> 8;                                                        // 波特率对应的重装载值
        AUXR |= 0x15;                                                           // 定时器2做波特率发生器    1T模式   启动定时器2
        busy = 0;                                                                                // 清零忙标志
}
void UartSend(char dat)                                // 发送字符函数
{
        while (busy);                                                                // 当串口忙时,等待
        busy = 1;                                                                                // 忙标志置1
        SBUF = dat;                                                                        // 发送数据dat
}
void UartSendStr(char *p)                        // 发送字符串函数
{while (*p)        {UartSend(*p++);}}                        // 逐个发送字符串的字符

void main()
{
        
        P2M0 = 0x00; P2M1 = 0x00;
        P3M0 = 0x00; P3M1 = 0x00;
        P2 = 0xff; P3 = 0xff;

        Timer0_Init();                                                        // 定时器0初始化
        Uart1Init();                                                                // 串口1初始化
        ES = 1;                                                                                        // 使能串口1中断
        EA = 1;                                                                                        // 使能EA总中断
        
        while (1)
        {
                if(KEY1 == 0)                                                                                                                // P3.2按键按下
                {
                        if(key1flag == 0)                                                                                        // 当按下标志为0时
                        {                                                                                                                                                        
                                if(B_1ms == 1) key1delay++;                                        // 按键延时,每1毫秒+1
                                if(key1delay >=10)                                                                        // 按下时间大于10毫秒
                                {key1delay = 0;key1flag = 1;UartSendStr("你好呀!\r\n");}                // 清零按键延时  按下标志置1  发送字符串“你好呀!”
                        }
                }
                if(KEY1 == 1){key1flag = 0;key1delay = 0;}         // 按键松开  清零按键按下标志  清零按键延时
                                                               
               
               
                if(KEY2 == 0)                                                                                                                // P3.3按键按下
                {
                        if(key2flag == 0)                                                                                        // 当按下标志为0时
                        {                                                                                                                                                        
                                if(B_1ms == 1) key2delay++;                                        // 按键延时,每1毫秒+1
                                if(key2delay >=10)                                                                        // 按下时间大于10毫秒
                                {key2delay = 0;key2flag = 1;UartSendStr("很高兴认识你!\n");}                // 清零按键延时  按下标志置1  发送字符串“很高兴认识你!”
                        }
                }
                if(KEY2 == 1){key2flag = 0;key2delay = 0;}         // 按键松开  清零按键按下标志  清零按键延时
               
               
               
                if(KEY3 == 0)                                                                                                                // P3.3按键按下
                {
                        if(key3flag == 0)                                                                                        // 当按下标志为0时
                        {                                                                                                                                                        
                                if(B_1ms == 1) key3delay++;                                        // 按键延时,每1毫秒+1
                                if(key3delay >=10)                                                                        // 按下时间大于10毫秒
                                {key3delay = 0;key3flag = 1;UartSendStr("祝你好运!\n");}                // 清零按键延时  按下标志置1  发送字符串“祝你好运!”
                        }
                }
                if(KEY3 == 1){key3flag = 0;key3delay = 0;}         // 按键松开  清零按键按下标志  清零按键延时
               
               
               
                if(KEY4 == 0)                                                                                                                // P3.3按键按下
                {
                        if(key4flag == 0)                                                                                        // 当按下标志为0时
                        {                                                                                                                                                        
                                if(B_1ms == 1) key4delay++;                                        // 按键延时,每1毫秒+1
                                if(key4delay >=10)                                                                        // 按下时间大于10毫秒
                                {key4delay = 0;key4flag = 1;UartSendStr("再见!\n");}                // 清零按键延时  按下标志置1  发送字符串“再见!”
                        }
                }
                if(KEY4 == 1){key4flag = 0;key4delay = 0;}         // 按键松开  清零按键按下标志  清零按键延时

}

void Timer0_Isr(void) interrupt 1
{
        B_1ms = 1;                                                                        // 1毫秒标志
}

void Uart1Isr() interrupt 4
{
        if (TI == 1)                                                                                        // 发送中断标志置1时
        {
                TI = 0;                                                                                // 清零发送中断标志
                busy = 0;                                                                        // 清零忙状态
        }
        if (RI == 1)                                                                                        // 接收中断标志置1时
        {
                RI = 0;
                P2 = ~SBUF;                                                                //P2口赋值SBUF取反结果

        }
}



串口学习-1.png
串口学习-2.png
串口学习-3.png
串口学习-4.png
串口学习-5.png
串口学习-6.png

UART1.mp4

2.55 MB, 下载次数: 165

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:443
  • 最近打卡:2025-05-09 10:10:53
已绑定手机

31

主题

142

回帖

1619

积分

金牌会员

积分
1619
发表于 2024-6-1 20:23:37 | 显示全部楼层
本帖最后由 未元星系 于 2024-6-1 20:25 编辑

自学开天斧第⑧课:
学习内容:1、掉电模式(也叫省电模式/停电模式/主时钟停振)  2、空闲模式
学习简介:STC8H8K64U单片机有两种低功耗模式:掉电模式和空闲模式。
                1、掉电模式:CPU和外设都停止工作。     2、空闲模式:CPU停止工作,外设正常运行。
                掉电模式可以通过定时器、中断、串口、比较器中断、低压检测中断、掉电唤醒定时器、I2C等方式唤醒
                使用低功耗模式需要调用电源控制寄存器PCON
实验项目:1.单片机一遍流水灯后进入掉电/空闲模式,P3.2口外部中断唤醒继续一边流水灯,再次进入掉电/空闲模式,循环这个过程。
程序代码:
#include <STC8H.H>
#define MAIN_Fosc  24000000L


void Delay_ms(unsigned int ms)
{unsigned int i;do{i = MAIN_Fosc / 10000;while(--i);}while(--ms);}

void main()
{
        unsigned char i;
        unsigned char a = 0x01;
        P2M0 = 0x00; P2M1 = 0x00;
        P3M0 = 0x00; P3M1 = 0xc3;
        P2 = 0x01;
        
        IT0 = 1;                    //外部中断0设置为下降沿触发
        EX0 = 1;                    //使能INT0
        EA = 1;                     //打开总中断
        
        while(1)
        {
                 for(i = 0;i < 8;i++)
                 {
                         P2 = ~(a << i);
                         Delay_ms(100);
                         P2 = 0xff;
                 }
                 PCON |= 0x02;  //开启掉电模式/ |= 0x01为省电模式
        }
}

void INT0_Routine(void)   interrupt 0
{}




低功耗1.png
低功耗2.png

掉电-空闲模式.mp4

3.29 MB, 下载次数: 165

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:443
  • 最近打卡:2025-05-09 10:10:53
已绑定手机

31

主题

142

回帖

1619

积分

金牌会员

积分
1619
发表于 2024-6-2 23:35:58 | 显示全部楼层
本帖最后由 未元星系 于 2024-6-2 23:41 编辑

自学开天斧第⑨课:
学习内容:1、printf函数串口打印
学习简介:我们初学C语言的第一课通常是printf打印"Hello World!",STC8H8K64U单片机也可以调用printf函数,将信息打印在串口助手里,使用这一功能需要以下操作:
                1、添加#inculde <stdio.h>头文件
                2、配置串口
                3、重构putchar函数
                4、调用printf函数
实验项目:单片机每隔1秒在串口助手打印一次数据;串口助手向单片机发送数据时,P2口LED按数据2进制亮灭。
程序代码:


#include <STC8H.H>
#include <stdio.h>

#define MAIN_Fosc   24000000L
#define BRT (65536 - (MAIN_Fosc / 115200+2) / 4)

bit busy;
bit B_1ms;                                                                                // 1毫秒标志
bit x;                                                                                //串口接收标志
sbit KEY1 = P3^5;        

int delay;                                                                    // 计时
unsigned char number1;                                // 测试变量,发送次数 unsigned char 类型
char number2;                                                                        // 测试变量,char 类型
unsigned int humidi;                                        // 测试变量,unsigned int 类型
int temper1;                                                                        // 测试变量,int  类型
int temper2;                                                                        // 测量变量,int  类型
float temper3;                                                                // 测试变量,float类型
float temper4;                                                                // 测试变量,float类型
unsigned char str[] = "STC8H8K64U-开天斧3.2";         // 字符串数组

void Delay_ms(unsigned int ms)
{
        unsigned int i;
        do{
                i = MAIN_Fosc / 10000;
                while(--i);
        }while(--ms);
}

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

void Uart1Init()                                                        // UART1初始化
{
        P_SW1 &= 0x3F;              //设置串口1引脚为P3.0,P3.1
        SCON = 0x50;                                                                // 模式1(8位数据)、接收使能
        PCON |= 0x00;               //设置波特率不加倍,关闭帧错检测功能
        T2L = BRT;                                                
        T2H = BRT >> 8;                                                        // 波特率对应的重装载值
        AUXR |= 0x15;
        busy = 0;                                                                                // 清零忙标志
}

void UartPutc(unsigned char dat)
{
        busy = 1;
        SBUF = dat;
        while(!TI);
        TI = 0;
        busy = 0;
}

char putchar(char c)                                                        //重构putchar函数
{
        UartPutc(c);
        return c;
}

void main()
{
        P2M0 = 0x00; P2M1 = 0x00;
        P3M0 = 0x00; P3M1 = 0x00;
        P2 = 0xff; P3 = 0xff;
        ES = 1;                                                                                        // 使能串口1中断
        EA = 1;                                                                                        // 使能EA总中断
        
        Timer0_Init();
        Uart1Init();
        
        temper1 = 25;                                                                // 测试变量,温度1 = 25度            int  类型,正数
        temper2 = -2;                                                                // 测试变量,温度2 = -2度                        int  类型,负数
        temper3 = 25.6;                                                        // 测试变量,温度3 = 25.6度                float类型,正数
        temper4 = -2.5;                                                        // 测试变量,温度4 = -2.5度                float类型,负数
        humidi = 50;                                                                // 测试变量,湿度  = 50 %                        unsigned int类型
        
        while(1)
        {                                                                                                                                                
                                if(B_1ms == 1)                                // 1毫秒到
                                {        
                                        B_1ms = 0;                                        // 清零1毫秒标志
                                        delay++;                                // 按键延时,每1毫秒+1
                                }                                       
                                if(delay >= 1000)                // 按下时间大于1000毫秒
                                {
                                        delay = 0;                        // 清零按键延时
                                        number1++;                                                                                                        // 每次发送后number1+1
                                        number2++;                                                                                                        // 每次发送后number2+1
          // Keil 扩展了 b h l,对应字节宽度,b-8位,h-16位(默认),l-32位
          // printf中有符号对应 %d,无符号对应%u 或 %x, 浮点型:%f,字符串 %s
          // u8  对应 %bu 或 %bx,        char 对应 %bd
          // u16 对应 %hu        或 %hx,        int  对应 %d 或 %hd
          // u32 对应 %lu 或 %lx,  long 对应 %ld
                                        printf("\n");
                                        printf("第%bu次发送\r   ",number1);        // 发送unsigned char类型,number1是u8类型,需要使用 %bu 或 %bx
                                        printf("第%bd次打印\r   ",number2);        // 发送 char类型,number2是 char类型,需要使用 %bd
                                        printf("湿度:%hu%%\r   ",humidi);                // 发送unsigned int  类型,humidi是 u16 类型,需要使用 %hu 或 %hx
                                        printf("温度1:%hd℃\r   ",temper1);                        // 发送  int 类型,temper是 int类型,需要使用 %hd
                                        printf("温度2:%hd℃\r   ",temper2);                        // 发送  int 类型,temper是 int 类型,需要使用 %hd
                                        printf("温度3:%4.1f℃\r   ",temper3);                                // 发送float类型,temper是 int 类型,需要使用 %f,2位整数,1位小数 %4.1f
                                        printf("温度4:%3.1f℃\r\n",temper4);                // 发送 float类型,temper是 int类型,需要使用 %f,1位整数,1位小数 %3.1f
                                        printf("%s\r   ",str);                                                                // 发送字符串"STC8H8K64U-开天斧三.2"
                                        printf("HelloWorld!\r\n\n");                                        // 发送字符串"HelloWorld!"
                                }
               
                if(x == 1)
                {
                        x = 0;
                        P2 = ~SBUF;
                }
               
        }
}

void Timer0_Routine(void) interrupt 1
{
        B_1ms = 1;                                                                        // 1毫秒标志
}

void Uart1Isr() interrupt 4
{
        if (TI == 1)                                                                                        // 发送中断标志置1时
        {
                TI = 0;                                                                                // 清零发送中断标志
                busy = 0;                                                                        // 清零忙状态
        }
        if (RI == 1)                                                                                        // 接收中断标志置1时
        {
                RI = 0;
                x = 1;
        }
}

(备注:视频演示发送的串口数据中,湿度出了错误,原因是一开始定义湿度取成了char类型,printf引用为int型,代码已纠正。)



printf.mp4

12.77 MB, 下载次数: 159

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:430
  • 最近打卡:2025-05-09 08:24:27
已绑定手机

19

主题

3196

回帖

4960

积分

论坛元老

积分
4960
发表于 2024-6-3 11:34:36 来自手机 | 显示全部楼层
学的真好
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:443
  • 最近打卡:2025-05-09 10:10:53
已绑定手机

31

主题

142

回帖

1619

积分

金牌会员

积分
1619
发表于 2024-6-3 11:52:59 | 显示全部楼层
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:443
  • 最近打卡:2025-05-09 10:10:53
已绑定手机

31

主题

142

回帖

1619

积分

金牌会员

积分
1619
发表于 2024-6-3 11:53:32 | 显示全部楼层

感谢认可,会继续坚持学习
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:443
  • 最近打卡:2025-05-09 10:10:53
已绑定手机

31

主题

142

回帖

1619

积分

金牌会员

积分
1619
发表于 2024-6-3 23:10:49 | 显示全部楼层
2024年6月3日,今天计划学习串口DMA发送与接收,DMA发送实验成功,但DMA接收代码仍有错误,暂未找出原因,明日继续学习。
4e477dc898f40800620509fe70b8a7d.jpg
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:358
  • 最近打卡:2025-05-09 00:47:13
已绑定手机

131

主题

1571

回帖

2042

积分

金牌会员

积分
2042
发表于 2024-6-4 00:58:54 来自手机 | 显示全部楼层
为什么你学的这么快,我学的那么慢啊
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-9 17:05 , Processed in 0.137595 second(s), 107 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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