神农鼎 发表于 2026-6-27 16:48:57

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

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


神农鼎 发表于 2026-6-27 16:49:12

<p>好的!下面我基于 <strong>STC8H8K64U</strong> 的数据手册和官方实验指导书,为你写一个完整的流水灯演示程序。</p>
<hr />
<h2>📌 硬件说明</h2>
<p>根据 STC8H8K64U 实验箱/开天斧的典型原理图:</p>
<ul>
<li><strong>LED 指示灯</strong>接在 <strong>P6 口</strong>(P6.0~P6.7),<strong>低电平点亮</strong></li>
<li><strong>P4.0</strong> 控制 PNP 三极管作为 LED 总电源开关,<strong>P4.0 输出 0 时总电源导通</strong></li>
<li>如果使用自己的最小系统板,请根据实际硬件调整端口</li>
</ul>
<hr />
<h2>📝 完整代码(使用定时器中断实现流水灯)</h2>
<pre><code class="language-c">/****************************************************************
* 文件名: main.c
* 功能: STC8H8K64U 流水灯演示程序
*         使用定时器0 1ms中断,每500ms切换一次流水灯
*         8个LED接P6口(低电平点亮),P4.0为总电源控制(低电平导通)
* 晶振: 使用内部IRC,建议设置为 11.0592MHz 或 24MHz
****************************************************************/

#include &quot;stc8h.h&quot;                     // STC8H头文件

#define LED_PORT   P6                // LED接P6口
#define LED_PIN_ALL0xFF            // 8位全亮/全灭值

// 流水灯方向定义
#define LEFT_TO_RIGHT0
#define RIGHT_TO_LEFT1

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

/******************** 毫秒级延时函数(查询方式) *******************/
void delay_ms(u16 ms)
{
    u16 i;
    for(i = 0; i &lt; 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 &amp;= ~0x80;      // 定时器0时钟12T模式

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

    // 以12MHz主频为例,12T模式,1ms定时
    // 实际请根据你的主频用ISP软件中的&quot;定时器计算器&quot;工具自动生成
    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 &amp;= ~0x01;      // P4.0 = 0,导通PNP三极管

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

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

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

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

      // 更新LED显示:将对应位置0(点亮),其余置1(熄灭)
      // 例: led_index=0 =&gt; 0xFE (点亮P6.0)
      //   led_index=1 =&gt; 0xFD (点亮P6.1)
      //   ...以此类推
      LED_PORT = ~(1 &lt;&lt; led_index);
    }
}
</code></pre>
<hr />
<h2>💡 使用说明 &amp; 重要提醒</h2>
<h3>1️⃣ 关于主频与定时器重装值</h3>
<p>上面的代码以 <strong>12MHz</strong> 主频为例写了定时初值。<strong>请根据你实际设置的主频</strong>,使用 <strong>STC-ISP(AIapp-ISP)下载软件</strong> 中的 <strong>&quot;定时器计算器&quot;</strong> 工具自动生成准确的定时器初值,更省心、更准确:</p>
<blockquote>
<p>ISP软件 → 定时器计算器 → 选择&quot;定时器0&quot; → 设置定时时间1ms → 自动生成代码</p>
</blockquote>
<h3>2️⃣ 如果你的LED不是接在P6口</h3>
<p>请修改 <code>GPIO_init()</code> 中的端口配置:</p>
<ul>
<li>改 <code>P6M0/P6M1</code> 为对应的 <code>PxM0/PxM1</code></li>
<li>改 <code>LED_PORT</code> 宏定义中的端口</li>
</ul>
<h3>3️⃣ 如果不需要P4.0总电源控制</h3>
<p>将 <code>GPIO_init()</code> 和 <code>main()</code> 中与 P4.0 相关的代码注释掉即可。</p>
<h3>4️⃣ 流水灯方向</h3>
<p>程序默认从左到右(P6.0 → P6.7),如需反转,将主循环里的 <code>dir</code> 变量改为 <code>RIGHT_TO_LEFT</code>。</p>
<h3>5️⃣ 不依赖定时器的极简版(软件延时)</h3>
<p>如果你不想用定时器,下面是一个最简单的软件延时流水灯版本:</p>
<pre><code class="language-c">#include &quot;stc8h.h&quot;

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

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

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

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

    while(1)
    {
      for(i = 0; i &lt; 8; i++)
      {
            P6 = ~(1 &lt;&lt; i);    // 逐位点亮
            delay_ms(300);   // 延时约300ms
      }
    }
}
</code></pre>
<hr />
<h2>📚 信息来源</h2>
<table>
<thead>
<tr>
<th>内容</th>
<th>来源</th>
</tr>
</thead>
<tbody>
<tr>
<td>I/O口模式配置(P6M0/P6M1)</td>
<td>STC8H数据手册<strong>第12章 配置I/O口</strong></td>
</tr>
<tr>
<td>实验箱LED硬件原理(P6口接LED,P4.0总电源)</td>
<td>STC8H实验指导书<strong>2.4~2.7 点灯实验</strong></td>
</tr>
<tr>
<td>定时器0配置</td>
<td>STC8H数据手册<strong>第16章 定时器/计数器</strong> —— 16.2.3/16.2.4</td>
</tr>
</tbody>
</table>
<blockquote>
<p>💬 如果在实际调试中遇到问题,欢迎继续提问!或者在 STC 官方论坛(<a href="http://www.stcaimcu.com">www.stcaimcu.com</a>)搜索更多示例。</p>
</blockquote>
<hr />
<p><a href="https://www.stcaimcu.com/plugin.php?id=twpx_xunsearch&amp;mod=forum&amp;q=%E5%B8%AE%E7%94%A8%20STC8H8K64U%E5%86%99%E4%B8%AA%E6%B5%81%E6%B0%B4%E7%81%AF%E7%9A%84%E6%BC%94%E7%A4%BA%E7%A8%8B%E5%BA%8F&amp;f=_all&amp;m=yes&amp;syn=yes&amp;s=relevance&amp;fid=0">🔍 搜索 &quot;帮用 STC8H8K64U写个流水灯的演示程序&quot;</a></p>
<p><strong>📌 相关论坛讨论</strong></p>
<ol>
<li><a href="https://www.stcaimcu.com/forum.php?mod=viewthread&amp;tid=257&amp;highlight=%E5%B8%AE%E7%94%A8STC8H8K64U%E5%86%99%E4%B8%AA%E6%B5%81%E6%B0%B4%E7%81%AF%E7%9A%84%E6%BC%94%E7%A4%BA%E7%A8%8B%E5%BA%8F&amp;page=1&amp;extra=#pid972">8H8K64U 实验箱演示程序包中有 LCD12864, LCD1602的演示程序</a></li>
<li><a href="https://www.stcaimcu.com/forum.php?mod=viewthread&amp;tid=17898&amp;highlight=%E5%B8%AE%E7%94%A8STC8H8K64U%E5%86%99%E4%B8%AA%E6%B5%81%E6%B0%B4%E7%81%AF%E7%9A%84%E6%BC%94%E7%A4%BA%E7%A8%8B%E5%BA%8F&amp;page=2&amp;extra=#pid167035">请教关于 AiCube的I2C的两个问题 | 已解决,最新修改在5楼</a></li>
<li><a href="https://www.stcaimcu.com/forum.php?mod=viewthread&amp;tid=2813&amp;highlight=%E5%B8%AE%E7%94%A8STC8H8K64U%E5%86%99%E4%B8%AA%E6%B5%81%E6%B0%B4%E7%81%AF%E7%9A%84%E6%BC%94%E7%A4%BA%E7%A8%8B%E5%BA%8F&amp;page=1&amp;extra=#pid19346">从8051到32位8051,何宾教授带大家一起穿越</a></li>
</ol>
页: [1]
查看完整版本: 帮用STC8H8K64U写个流水灯的演示程序