基于三段式状态机设计的思想实现流水灯,花型要求如下: • 从左到右依次点亮,从左到右依次灭 • 从中间向两边依次亮,从中间向两边依次灭(2 遍) • 从两边向中间依次亮,从两边向中间依次灭(2 遍) • 如此反复循环…… 完成基于状态机的流水灯设计,并下板实现。 基础要求: 使用 EG4S20 使用 PLL 生成 50M 时钟, 0.5S 移位一次 使用 8 个 LED 使用移位寄存器控制 LED 代码限制到 200 行内
时间: 2024-03-25 08:39:31 浏览: 51
好的,让我来为你解答这个问题。首先,我们需要了解三段式状态机的设计思想。三段式状态机是基于有限状态机的一种设计思想,将有限状态机的状态分为三个阶段:启动阶段、运行阶段和停止阶段。在启动阶段,状态机初始化并准备开始运行;在运行阶段,状态机根据输入信号的变化转换状态并执行相应的操作;在停止阶段,状态机清理并停止运行。
接下来,我们可以根据题目要求设计如下的三段式状态机:
启动阶段:LED1 亮,其他 LED 灭;
运行阶段:
状态1:从左到右依次点亮,从左到右依次灭;
状态2:从中间向两边依次亮,从中间向两边依次灭(2 遍);
状态3:从两边向中间依次亮,从两边向中间依次灭(2 遍);
状态4:重复状态1~3;
停止阶段:LED1 灭,其他 LED 灭。
接下来,我们需要根据状态机的设计来编写代码。代码如下:
```C
#include "EG4S20.h" // 引入 EG4S20 头文件
#include "shiftregister.h" // 引入移位寄存器头文件
// 状态定义
#define STATE_START 0 // 启动阶段
#define STATE_LEFT_RIGHT 1 // 从左到右
#define STATE_MIDDLE_OUT 2 // 从中间向两边
#define STATE_OUT_MIDDLE 3 // 从两边向中间
#define STATE_REPEAT 4 // 重复状态1~3
#define STATE_STOP 5 // 停止阶段
// 定义 LED 状态数组
int led_state[8] = {1,0,0,0,0,0,0,0}; // 初始化 LED1 亮,其他灭
// 定义计时器变量和计时器常量
int timer = 0;
const int TIMER_MAX = 25; // 0.5s 移位一次
// 定义状态机变量和状态机常量
int state = STATE_START;
const int STATE_MAX = 5; // 状态数为5
// 状态机函数
void state_machine() {
switch(state) {
case STATE_START:
// 启动阶段,初始化 LED 状态数组
led_state[0] = 1;
for(int i=1; i<8; i++) {
led_state[i] = 0;
}
// 转换到状态1
state = STATE_LEFT_RIGHT;
break;
case STATE_LEFT_RIGHT:
// 从左到右依次点亮,从左到右依次灭
if(timer == TIMER_MAX) {
// 移位
for(int i=0; i<7; i++) {
led_state[i] = led_state[i+1];
}
led_state[7] = 0;
// 判断是否完成状态
if(led_state[0] == 1) {
// 完成状态,转换到状态2
state = STATE_MIDDLE_OUT;
}
// 重置计时器
timer = 0;
}
break;
case STATE_MIDDLE_OUT:
// 从中间向两边依次亮,从中间向两边依次灭(2 遍)
if(timer == TIMER_MAX) {
// 移位
for(int i=0; i<4; i++) {
led_state[i] = 0;
led_state[7-i] = 0;
}
// 判断是否完成状态
if(led_state[3] == 1) {
// 完成状态,转换到状态3
state = STATE_OUT_MIDDLE;
}
// 重置计时器
timer = 0;
}
break;
case STATE_OUT_MIDDLE:
// 从两边向中间依次亮,从两边向中间依次灭(2 遍)
if(timer == TIMER_MAX) {
// 移位
for(int i=0; i<4; i++) {
led_state[i] = 1;
led_state[7-i] = 1;
}
// 判断是否完成状态
if(led_state[0] == 1) {
// 完成状态,转换到状态4
state = STATE_REPEAT;
}
// 重置计时器
timer = 0;
}
break;
case STATE_REPEAT:
// 重复状态1~3
if(timer == TIMER_MAX) {
// 判断是否完成状态
if(state != STATE_LEFT_RIGHT) {
// 未完成,返回状态1
state = STATE_LEFT_RIGHT;
} else {
// 已完成,转换到状态2
state = STATE_MIDDLE_OUT;
}
// 重置计时器
timer = 0;
}
break;
case STATE_STOP:
// 停止阶段,灭掉所有 LED
for(int i=0; i<8; i++) {
led_state[i] = 0;
}
break;
}
// 更新移位寄存器
update_shiftregister(led_state);
// 计时器加一
timer++;
}
int main() {
// 初始化 EG4S20
init_EG4S20();
// 使用 PLL 生成 50M 时钟
set_pll(50);
// 初始化移位寄存器
init_shiftregister();
// 循环执行状态机
while(1) {
state_machine();
}
return 0;
}
```
代码限制在 200 行内,所以注释不是很详细。如果有疑问,请随时提出。
阅读全文