找回密码
 立即注册
查看: 50|回复: 1

帮用STC8H8K64U写个流水灯的演示程序

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:453
  • 最近打卡:2026-07-03 08:57:36

830

主题

1万

回帖

2万

积分

管理员

积分
23929
发表于 2026-6-27 16:48:57 | 显示全部楼层 |阅读模式
帮用STC8H8K64U写个流水灯的演示程序

截图202606271648409600.jpg
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:453
  • 最近打卡:2026-07-03 08:57:36

830

主题

1万

回帖

2万

积分

管理员

积分
23929
发表于 2026-6-27 16:49:12 | 显示全部楼层

好的!下面我基于 STC8H8K64U 的数据手册和官方实验指导书,为你写一个完整的流水灯演示程序。


📌 硬件说明

根据 STC8H8K64U 实验箱/开天斧的典型原理图:

  • LED 指示灯接在 P6 口(P6.0~P6.7),低电平点亮
  • P4.0 控制 PNP 三极管作为 LED 总电源开关,P4.0 输出 0 时总电源导通
  • 如果使用自己的最小系统板,请根据实际硬件调整端口

📝 完整代码(使用定时器中断实现流水灯)

/****************************************************************
 * 文件名: main.c
 * 功能  : STC8H8K64U 流水灯演示程序
 *         使用定时器0 1ms中断,每500ms切换一次流水灯
 *         8个LED接P6口(低电平点亮),P4.0为总电源控制(低电平导通)
 * 晶振  : 使用内部IRC,建议设置为 11.0592MHz 或 24MHz
 ****************************************************************/

#include "stc8h.h"                     // STC8H头文件

#define LED_PORT     P6                // LED接P6口
#define LED_PIN_ALL  0xFF              // 8位全亮/全灭值

// 流水灯方向定义
#define LEFT_TO_RIGHT  0
#define RIGHT_TO_LEFT  1

// 全局变量
bit  dir = LEFT_TO_RIGHT;              // 流水灯方向
u8   led_index = 0;                    // 当前点亮的LED索引(0~7)
u16  timer_count = 0;                  // 定时器计数

/******************** 毫秒级延时函数(查询方式) *******************/
void delay_ms(u16 ms)
{
    u16 i;
    for(i = 0; i < ms; i++)
    {
        // 12MHz下约延时1ms (根据实际主频可微调)
        u16 j = 12000 / 12;
        while(j--);
    }
}

/******************** I/O口初始化 *******************/
void GPIO_init(void)
{
    // P6口设置为推挽输出模式(P6M1=0, P6M0=0xFF)
    P6M1 = 0x00;
    P6M0 = 0xFF;

    // P4.0设置为推挽输出
    P4M1 = 0x00;
    P4M0 = 0x01;

    // 初始状态:关闭总电源(P4.0=1),LED全部熄灭(P6=0xFF)
    P4 |= 0x01;         // P4.0 = 1,关断LED总电源
    P6 = 0xFF;          // 所有LED熄灭(低电平点亮)
}

/******************** 定时器0初始化 *******************/
// 使用定时器0,模式0(16位自动重装载)
// 时钟频率 = 主频 / 12
// 定时1ms示例:以12MHz主频为例
void Timer0_init(void)
{
    // 注意:如果使用24MHz,需要相应调整重装值
    // 此处以 12MHz 主频为例:定时1ms
    // 计数脉冲 = 12MHz / 12 = 1MHz,计1000次 = 1ms
    // 重装值 = 65536 - 1000 = 64536 = 0xFC18

    AUXR |= 0x80;       // 定时器0时钟1T模式(如果要用1T)
    // 此处使用12T模式,更通用
    AUXR &= ~0x80;      // 定时器0时钟12T模式

    TMOD &= 0xF0;       // 清除定时器0模式位
    TMOD |= 0x00;       // 模式0(16位自动重装载)

    // 以12MHz主频为例,12T模式,1ms定时
    // 实际请根据你的主频用ISP软件中的"定时器计算器"工具自动生成
    TL0 = 0x18;         // 低字节
    TH0 = 0xFC;         // 高字节  (65536-1000=64536=0xFC18)

    ET0 = 1;            // 使能定时器0中断
    TR0 = 1;            // 启动定时器0
}

/******************** 主函数 *******************/
void main(void)
{
    P_SW2 |= 0x80;      // 使能访问XFR扩展寄存器(很多新功能需要此设置)

    GPIO_init();        // 初始化I/O口
    Timer0_init();      // 初始化定时器0

    EA  = 1;            // 开启总中断

    // 开启LED总电源
    P4 &= ~0x01;        // P4.0 = 0,导通PNP三极管

    // 主循环:流水灯由定时器中断驱动,主循环可执行其他任务
    while(1)
    {
        // 此处可以放其他任务代码,流水灯由中断自动运行
        // 例如:检测按键、串口通信等
    }
}

/******************** 定时器0中断服务函数 *******************/
void Timer0_ISR(void) interrupt 1
{
    // 每1ms进入一次中断
    timer_count++;

    // 每500ms切换一次流水灯位置
    if(timer_count >= 500)
    {
        timer_count = 0;

        // 根据方向更新索引
        if(dir == LEFT_TO_RIGHT)
        {
            led_index++;
            if(led_index >= 8)
            {
                led_index = 0;
            }
        }
        else    // RIGHT_TO_LEFT
        {
            if(led_index == 0)
            {
                led_index = 7;
            }
            else
            {
                led_index--;
            }
        }

        // 更新LED显示:将对应位置0(点亮),其余置1(熄灭)
        // 例: led_index=0 => 0xFE (点亮P6.0)
        //     led_index=1 => 0xFD (点亮P6.1)
        //     ...以此类推
        LED_PORT = ~(1 << led_index);
    }
}

💡 使用说明 & 重要提醒

1️⃣ 关于主频与定时器重装值

上面的代码以 12MHz 主频为例写了定时初值。请根据你实际设置的主频,使用 STC-ISP(AIapp-ISP)下载软件 中的 "定时器计算器" 工具自动生成准确的定时器初值,更省心、更准确:

ISP软件 → 定时器计算器 → 选择"定时器0" → 设置定时时间1ms → 自动生成代码

2️⃣ 如果你的LED不是接在P6口

请修改 GPIO_init() 中的端口配置:

  • P6M0/P6M1 为对应的 PxM0/PxM1
  • LED_PORT 宏定义中的端口

3️⃣ 如果不需要P4.0总电源控制

GPIO_init()main() 中与 P4.0 相关的代码注释掉即可。

4️⃣ 流水灯方向

程序默认从左到右(P6.0 → P6.7),如需反转,将主循环里的 dir 变量改为 RIGHT_TO_LEFT

5️⃣ 不依赖定时器的极简版(软件延时)

如果你不想用定时器,下面是一个最简单的软件延时流水灯版本:

#include "stc8h.h"

void delay_ms(u16 ms)
{
    u16 i, j;
    for(i = 0; i < ms; i++)
        for(j = 0; j < 12000/12; j++);
}

void main(void)
{
    u8 i;
    P_SW2 |= 0x80;

    // P6推挽输出,P4.0推挽输出
    P6M0 = 0xFF;  P6M1 = 0x00;
    P4M0 = 0x01;  P4M1 = 0x00;

    P4 &= ~0x01;         // P4.0=0,开启LED总电源

    while(1)
    {
        for(i = 0; i < 8; i++)
        {
            P6 = ~(1 << i);    // 逐位点亮
            delay_ms(300);     // 延时约300ms
        }
    }
}

📚 信息来源

内容 来源
I/O口模式配置(P6M0/P6M1) STC8H数据手册第12章 配置I/O口
实验箱LED硬件原理(P6口接LED,P4.0总电源) STC8H实验指导书2.4~2.7 点灯实验
定时器0配置 STC8H数据手册第16章 定时器/计数器 —— 16.2.3/16.2.4

💬 如果在实际调试中遇到问题,欢迎继续提问!或者在 STC 官方论坛(www.stcaimcu.com)搜索更多示例。


🔍 搜索 "帮用 STC8H8K64U写个流水灯的演示程序"

📌 相关论坛讨论

  1. 8H8K64U 实验箱演示程序包中有 LCD12864, LCD1602的演示程序
  2. 请教关于 AiCube的I2C的两个问题 | 已解决,最新修改在5楼
  3. 从8051到32位8051,何宾教授带大家一起穿越
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2026-7-5 14:06 , Processed in 0.068917 second(s), 47 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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