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

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

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

131

主题

1571

回帖

2042

积分

金牌会员

积分
2042
发表于 2024-6-4 01:00:27 来自手机 | 显示全部楼层
看了你的按键控制多个模式
如果就一个按键,可以控制吗?
比如默认熄灭,按一下打开led用模式 1闪,再按 模式 2闪,再按模式 3闪
回复 支持 反对

使用道具 举报 送花

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

31

主题

142

回帖

1619

积分

金牌会员

积分
1619
发表于 2024-6-4 07:35:41 来自手机 | 显示全部楼层
vb2002 发表于 2024-6-4 01:00
看了你的按键控制多个模式
如果就一个按键,可以控制吗?
比如默认熄灭,按一下打开led用模式 1闪,再按 模 ...

可以的,定义一个按键次数变量,按一下按键给它加一,用if()检测就可以
回复 支持 反对

使用道具 举报 送花

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

31

主题

142

回帖

1619

积分

金牌会员

积分
1619
发表于 2024-6-4 07:58:07 | 显示全部楼层
本帖最后由 未元星系 于 2024-6-4 08:03 编辑
vb2*** 发表于 2024-6-4 00:58
为什么你学的这么快,我学的那么慢啊

我可能是因为之前跟着b站江协科技的教程学了两遍51单片机(STC89C52),所以有些单片机基础;另外我找到了一套教程,b站布丁橘长的,在咱们论坛里上方的教学视频里的“屠龙刀演示”也是,虽然是讲STC32G单片机的,但基础方面和我学的8H差不多,时长很短但全是干货,也推荐你看看。最后是看看数据手册,对应的功能看明白了就学得很快。
回复 支持 反对

使用道具 举报 送花

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

19

主题

3196

回帖

4960

积分

论坛元老

积分
4960
发表于 2024-6-4 08:19:25 来自手机 | 显示全部楼层
vb2002 发表于 2024-6-4 01:00
看了你的按键控制多个模式
如果就一个按键,可以控制吗?
比如默认熄灭,按一下打开led用模式 1闪,再按 模 ...

这个不就是标志位算法吗
回复 支持 反对

使用道具 举报 送花

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

131

主题

1571

回帖

2042

积分

金牌会员

积分
2042
发表于 2024-6-4 09:03:12 | 显示全部楼层
未元*** 发表于 2024-6-4 07:58
我可能是因为之前跟着b站江协科技的教程学了两遍51单片机(STC89C52),所以有些单片机基础;另外我找到了 ...

基础我也有点了
就像老师讲的,一看就懂,一写就废~
回复 支持 反对

使用道具 举报 送花

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

131

主题

1571

回帖

2042

积分

金牌会员

积分
2042
发表于 2024-6-4 09:04:45 | 显示全部楼层
so*** 发表于 2024-6-4 08:19
这个不就是标志位算法吗

标志位算法
如果加上储存功能呢?
比如按一下换挡(记忆),5秒后没换档,下一次按就关灯.
再下一次按就是开机,打开上一次记忆的模式
回复 支持 反对

使用道具 举报 送花

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

131

主题

1571

回帖

2042

积分

金牌会员

积分
2042
发表于 2024-6-4 09:07:42 | 显示全部楼层
未元*** 发表于 2024-5-27 22:57
自学开天斧第⑤课:
学习内容:1、外部中断
学习简介:STC8H8K64U单片机内置五个外部中断,INT0,INT1,INT2, ...

我记得电容可以做硬件消抖
按键两端并上0.1uf电容
回复 支持 反对

使用道具 举报 送花

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

1

主题

836

回帖

1529

积分

金牌会员

积分
1529
发表于 2024-6-4 09:15:43 | 显示全部楼层
靡不有初,鲜克有终
回复

使用道具 举报 送花

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

31

主题

142

回帖

1619

积分

金牌会员

积分
1619
发表于 2024-6-4 11:54:09 | 显示全部楼层
vb2*** 发表于 2024-6-4 09:07
我记得电容可以做硬件消抖
按键两端并上0.1uf电容

挺好的办法
回复 支持 反对

使用道具 举报 送花

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

31

主题

142

回帖

1619

积分

金牌会员

积分
1619
发表于 2024-6-4 22:30:10 | 显示全部楼层
本帖最后由 未元星系 于 2024-6-4 22:35 编辑

自学开天斧第⑩课:
学习内容:1、串口DMA发送与接收
学习简介:串口通信是单片机和电脑通信的常用方法,但当需要一次发送的数据总量很大时,就会严重占用主程序时间,为了避免这个问题,我们可以将需要串口发送的数据存到DMA里发送,这样会提高单片机运行效率,减少主函数占用。串口DMA一次最多可以发送或接收256字节数据(可自行调整为小于256字节的数据)
实验项目:单片机向串口发送256字节数据->P2口灯亮灭两次->检测DMA输入(若有输入则打印在串口上)
实验重点:为体现DMA使用对主程序效率的影响,串口波特率设置为9600

程序代码:


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

#define MAIN_Fosc   24000000L
#define BRT (65536 - (MAIN_Fosc / 9600+2) / 4)
#define DMA_AMT_LEN 255                         // DMA传输总字节(AMT+1) 9999+1=10000字节
unsigned char xdata DMABuffer_send[256];                // DMA发送缓存       DMA数据存放在XRAM(XDATA区域),需要使用关键字xdata
unsigned char xdata DMABuffer_review[256];       //DMA接收缓存
unsigned int j,k;
bit busy;
bit B_1ms;                                                                                // 1毫秒标志
bit        DmaTxFlag;                                                                // 发送完成标志
bit        DmaRxFlag;                                                                // 接收完成标志

//unsigned int numb;
unsigned char Rx_cnt;                                                                                // Rx接收计数
unsigned char RX_TimeOut;

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

void Timer0_Init(void)                                // 1毫秒@24MHz
{
        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 Blink()                                                                        
{unsigned char i;for(i = 0;i < 4;i++){P2 = ~P2;Delay_ms(100);}}  //P2口灯亮灭两次

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)
{
        UartPutc(c);
        return c;
}

void DMA_Config(void)
{
        DMA_UR1T_CFG = 0x80;                                // bit7 1:使能串口1DMA发送中断
        DMA_UR1T_STA = 0x00;                                // 清零串口1DMA发送完成中断标志、清零数据覆盖中断标志
        DMA_UR1T_AMT =  DMA_AMT_LEN;                                                                // 设置传输总字节数:n+1
        DMA_UR1T_TXAH = (unsigned char)((unsigned int)&DMABuffer_send >> 8);        // 设置传输数据的源地址,高8位
        DMA_UR1T_TXAL = (unsigned char)((unsigned int)&DMABuffer_send);                        // 设置传输数据的源地址,低8位
        DMA_UR1T_CR = 0xc0;                                        // bit7 1:使能串口1DMA发送, bit6 1:开始DMA自动发送

        DMA_UR1R_CFG = 0x80;                                // bit7 1:使能串口1DMA接收中断
        DMA_UR1R_STA = 0x00;                                // 清零串口1DMA接收完成中断标志、清零数据丢弃中断标志
        DMA_UR1R_AMT =  DMA_AMT_LEN;                                                                // 设置传输总字节数:n+1
        DMA_UR1R_RXAH = (unsigned char)((unsigned int)&DMABuffer_review >> 8);        // 设置传输数据的目标地址,高8位
        DMA_UR1R_RXAL = (unsigned char)((unsigned int)&DMABuffer_review);                        // 设置传输数据的目标地址,低8位
        DMA_UR1R_CR = 0xa1;                                        //bit7 1:使能串口1DMA接收, bit5 1:开始DMA自动接收, bit0 1:清除 FIFO
}


void main()
{
        P3M0 = 0x00; P3M1 = 0x00;
  P2M0 = 0x00; P2M1 = 0x00;
        P_SW2 |= 0x80;                 //使能XFR
        ES = 1;                                                                                        // 使能串口1中断
        EA = 1;                                                                                        // 使能EA总中断
        
        Timer0_Init();
        Uart1Init();
        DMA_Config();                                                                                       
        
        DmaTxFlag = 0;                                                        // 清零发送完成标志
        DmaRxFlag = 0;                                                        // 清零接收完成标志

        for(k = 0;k < 256; k++)                // 200个字符
        {
                DMABuffer_send[k] = k%128;                        // 200个字符,为128个ASCII字符
        }
        while (1)
        {
                DmaTxFlag = 1;
                DmaRxFlag = 1;
                if((DmaTxFlag) && (DmaRxFlag))        // 当发送和接收完成标志均为1时,表示空闲
                {
                   DmaTxFlag = 0;                                        // 清零发送完成标志
                   DMA_UR1T_CR = 0xc0;                        // bit7 1:使能 UART1_DMA, bit6 1:开始 UART1_DMA 自动发送
                   DmaRxFlag = 0;                                        // 清零接收完成标志
                   DMA_UR1T_CR = 0xa1;                        // bit7 1:使能 UART1_DMA, bit5 1:开始 UART1_DMA 自动接收, bit0 1:清除 FIFO
                }
    Blink();
               
                DmaTxFlag = 0;                                                        // 清零发送完成标志
          DmaRxFlag = 0;                                                        // 清零接收完成标志
                if((DmaTxFlag) && (DmaRxFlag))        // 当发送和接收完成标志均为1时,表示空闲
                {
                        Rx_cnt = 0;                                                        // 清零接收计数
                        RX_TimeOut = 0;                                // 清零接收超时计数
                        DmaTxFlag = 0;                                        // 清零发送完成标志
                        DMA_UR1T_CR = 0xc0;                        // bit7 1:使能 UART1_DMA, bit6 1:开始 UART1_DMA 自动发送
                        DmaRxFlag = 0;                                        // 清零接收完成标志
                        DMA_UR1R_CR = 0xa1;                        // bit7 1:使能 UART1_DMA, bit5 1:开始 UART1_DMA 自动接收, bit0 1:清除 FIFO
                }
               
                if(B_1ms)                                                                 //1ms 到
                {
                        B_1ms = 0;
                        if(RX_TimeOut > 0)                        // 超时计数
                        {
                                if(--RX_TimeOut == 0)                                                // 接收超时计数
                                {
                                        DMA_UR1R_CR = 0x00;                                         // 关闭 UART1_DMA
                                        printf("\n以下是已接收到的数\xFD据:\r\n");         // UART1 发送 一个字符串,\xFD用于补全汉字‘数’的编码,防止出现乱码
                                        for(j=0;j<Rx_cnt;j++) printf("%bc",DMABuffer_review[j]);                // 将接收到的数据,发送给PC端
                                        printf("\r\n");                                                                // 数据发送完成后,发送回车、换行符
                                        Rx_cnt = 0;                                                                                // 清零接收计数
                                        DMA_UR1R_CR = 0xa1;                                         //bit7 1: 使能UART1_DMA,bit5 1: 开始 UART1_DMA 自动接收,bit0 1: 清除 FIFO
                                }
                        }
                }
        }
}

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

void Uart1Isr() interrupt 4
{
        if (TI == 1){TI = 0;busy = 0;}
        if (RI == 1)
        {
                RI = 0;
                Rx_cnt++;                                                                        // 接收计数+1
                if(Rx_cnt > DMA_AMT_LEN) {Rx_cnt = 0;}                // 接收计数大于等于DMA缓冲区长度,清零接收计数
                RX_TimeOut = 5;                                 // 如果 5ms 没收到新的数据,判定一串数据接收完毕x = 1;}
        }
}


void UART1_DMA_Interrupt(void) interrupt 13                // 串口DMA中断号大于31,借用13号保留中断中转
{                                                                                
        if (DMA_UR1T_STA & 0x01)                // 发送完成中断标志为1时
        {
                DMA_UR1T_STA &= ~0x01;                // 清零发送完成中断标志
                DmaTxFlag = 1;                                                // 发送完成标志置1
        }
        if (DMA_UR1T_STA & 0x04)                // 数据覆盖中断标志为1时
        {
                DMA_UR1T_STA &= ~0x04;                // 清零数据覆盖中断标志
        }
        if (DMA_UR1R_STA & 0x01)                // 接收完成中断标志为1时
        {
                DMA_UR1R_STA &= ~0x01;                // 清零接收完成中断标志
                DmaRxFlag = 1;                                                // 接收完成标志置1
        }
        if (DMA_UR1R_STA & 0x02)                // 数据丢弃中断标志为1时
        {
                DMA_UR1R_STA &= ~0x02;                // 清零数据丢弃中断标志
        }
}

实验现象:单片机向串口发送256字节数据->P2口灯亮灭两次->检测DMA输入(若有输入则打印在串口上),串口发送接收数据不打断P2口LED按其频率闪烁




屏幕截图 2024-06-04 222023.png
屏幕截图 2024-06-04 222030.png
屏幕截图 2024-06-04 222036.png
屏幕截图 2024-06-04 222043.png
屏幕截图 2024-06-04 222119.png
屏幕截图 2024-06-04 222131.png
屏幕截图 2024-06-04 222143.png
屏幕截图 2024-06-04 222153.png

DMA.mp4

10.43 MB, 下载次数: 146

回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-9 17:06 , Processed in 0.131025 second(s), 114 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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