8254跑马灯c语言程序,C语言笔记-基于C语言实现的流水跑马灯

今天,偶忽然想起大二时学跑马灯,当时一个个敲代码最后运行出来跑马灯的状态,我现在都还记得,把代码运行到实体上最后呈现的效果真是令人愉悦,话不多说,下面我将就跑马灯制作流程给大家分享一下。

1.题目:跑马灯

(1)基本要求

采用8254精确定时,LED的点亮规律为LED8-LED1,每一个LED的点亮时间间隔由逻辑电平开关K1、K2与K3选择。K1的时间间隔为0.5S,K2的时间间隔为1.0S,K3的时间间隔为1.5S。当主机键盘按下任意键时停止演示。

(2)设计提示

采用8255的A口接LED灯,B口接逻辑电平开关K1、K2与K3。在8254的中断服务程序中完成对灯的控制,主程序检测开关的变化,改变点亮LED灯的时间间隔。

(3)进一步设计要求

LED的点亮规律变为LED8-LED1-LED8

2.分析:基本原理设计

步骤一:8255采用B口工作在方式0,进行输入,获取开关(注:为了便于进行课设操作,我们采用了K2,K1,K0以此来取代K3,K2,K1,实现的要求完全一致)K2K1K0的值,这里会有三个值,分别是二进制编码的100,010,001,即十进制的4,2,1,分别对应LED灯点亮的时间间隔1.5s,1.0s,0.5s。步骤二:8254采用工作方式三,产生一个固定频率的方波,去不断触发中断服务程序。在主程序中,获取8255的B口输入值,根据输入值给8254的计数器1写入对应的初始值,在OUT1端就能得到一个固定频率的方波信号,这里我们连接了一个K7所对应的灯,以此来进行验证方波的产生以及通过灯闪烁的频率可以大致判断方波的频率,来对应时间间隔1.5s,1.0s,0.5s。步骤三:8254产生的方波信号输出,连接到中断接口IR10,用来利用方波信号的频率按照一定的时间间隔来出发中断服务程序。步骤四:中断服务程序按照8254的方波频率,在一定的时间间隔内被加载执行。在中断服务程序中实现对8255的A口输出的改变,来控制LED7-LED0的闪烁变化,即实现跑马灯。

3.代码实现://******************************************************************************************************************

/*

实验接线:

8254:

片选信号CS接Y0;GATE0、GATE1级联接+5V;CLK0接1MHz;CLK1接OUT0;

OUT1接k5(进行8254的方波显示);

8255:

片选信号CS接Y1;A口作为输出用排线接LED灯;PB0、PB1、PB2作为输入分别接K0、K1、K2;

中断:

IR10接OUT1(中断控制程序控制LED灯的闪烁变化);

*/

//******************************************************************************************************************

//8255模块的设置

void init(void);//初始化

voidISR(void);

int i=0,j=0;

const unsigned short

Port8255Base = 0x288;

const unsigned char

ControlWord8255 = 0x82;

void init8255(void);// 8255初始化

//******************************************************************************************************************

//关于8254模块的设置

//通道0: 控制字00110110 -> 36H,即0x36,CLK0=1MHz,OUT0=0.01s,初值=F(clk)*T(out) 初始值:COUNT0=10000

//通道1: 控制字01110110 -> 76H,即0x76,CLK1=OUT0,初值=T1(out)/T1(clk)

//当OUT1=0.5s,k3=0,k2=0,k0=1,1 初始值:COUNT1=50

//当OUT1=1.0s,k3=0,k2=1,k0=0,2 初始值:COUNT1=100

//当OUT1=1.5s,k3=1,k2=0,k0=0,4 初始值:COUNT1=150

voidinit8254(void);// 8254初始化

const unsigned short

Port8254Base = 0x280, //计数器1端口地址为p8254Base+1,端口地址为p8254Base+3.

counter0=10000;

const unsigned char

ControlWord8254ch0 = 0x36, ControlWord8254ch1 = 0x76;

unsigned short

counter1=100;//计数器初值

byte pData;

unsigned char pdata=0x80;

bool flag=true;

//******************************************************************************************************************

//主函数

void main()

{

init();

init8254();// 8254初始化

init8255();//8255初始化

printf("\n start...\n");

while (!_kbhit())

{

PortReadByte(Port8255Base + 1, &pData);

//写入计数器1的初始值

if(pData==1){

//k0为1的情况,k2k1k0=001,即时间间隔为0.5秒

counter1=50;

PortWriteByte(Port8254Base+1 , counter1%256); // 写计数器1计数初值低8位

PortWriteByte(Port8254Base+1 , counter1/256); // 写计数器1计数初值高8位

printf("=switch state:%x LED灯点亮间隔0.5秒=\n",pData);

}

if(pData==2){

//k1为1的情况,k2k1k0=010,即时间间隔为1.0秒

counter1=100;

PortWriteByte(Port8254Base+1 , counter1%256); // 写计数器1计数初值低8位

PortWriteByte(Port8254Base+1 , counter1/256); // 写计数器1计数初值高8位

printf("=switch state:%x LED灯点亮间隔1.0秒=\n",pData);

}

if(pData==4){

//k2为1的情况,k2k1k0=100,即时间间隔为1.5秒

counter1=150;

PortWriteByte(Port8254Base+1 , counter1%256); // 写计数器1计数初值低8位

PortWriteByte(Port8254Base+1 , counter1/256); // 写计数器1计数初值高8位

printf("=switch state:%x LED灯点亮间隔1.5秒=\n",pData);

}

sleep(3000);// delay 1s

EnableIntr(); // 开中断,功能等效于汇编语言指令sti

RegisterLocalISREx(ISR,10); // 加载中断服务程

printf("Wait for the switch state change...\n\n");

}

_getch();

printf("\n Press any key over...\n");

//DisableIntr(); // 开中断,功能等效于汇编语言指令cli

Cleanup();

}

//中断服务程序,实现跑马灯的流水

voidISR(void)

{

if(flag)

{

_asm

{

ror pdata,1 //循环右移指令

}

}

else

{

_asm

{

rol pdata,1 //循环左移指令

}

}

j++;

if(j==7)

{

flag = false;

}

if(j==14){

flag = true;

j=0;

}

PortWriteByte(Port8255Base,pdata);

}

//机箱的初始化

void init(void)

{

if(!Startup())// 加载实验平台I/O驱动程序

{

printf("\n\n ERROR: Open Device Error!请打开实验箱电源\n");

_getch();

exit(0); // return to Windows

}

}

//8254初始化

voidinit8254(void)

{

PortWriteByte(Port8254Base + 3, ControlWord8254ch0); // 写计数器0控制字

PortWriteByte(Port8254Base + 3, ControlWord8254ch1); // 写计数器1控制字

PortWriteByte(Port8254Base , counter0%256); // 写计数器0计数初值低8位

PortWriteByte(Port8254Base , counter0/256); // 写计数器0计数初值高8位

}

//8255初始化

voidinit8255(void)

{

PortWriteByte(Port8255Base + 3, ControlWord8255); // 写8255控制字

PortWriteByte(Port8255Base,pdata);

}

【推荐课程:C视频教程】

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,跑马灯程序是一种常见的 LED 灯条效果,下面是嵌入式 C 语言实现 100 个跑马灯程序的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #include <windows.h> // 定义 LED 灯的数量 #define LED_NUM 8 // 定义每个 LED 灯的状态 typedef struct { int state; } LED; // 初始化 LED 灯的状态 void init_led(LED *led, int num) { for (int i = 0; i < num; i++) { led[i].state = 0; } } // 更新 LED 灯的状态 void update_led(LED *led, int num) { for (int i = 0; i < num; i++) { if (led[i].state == 1) { printf("*"); } else { printf("-"); } } printf("\n"); } // 跑马灯程序1:从左到右移动 void program_1(LED *led, int num) { for (int i = 0; i < num; i++) { led[i].state = 1; update_led(led, num); led[i].state = 0; Sleep(100); } } // 跑马灯程序2:从右到左移动 void program_2(LED *led, int num) { for (int i = num - 1; i >= 0; i--) { led[i].state = 1; update_led(led, num); led[i].state = 0; Sleep(100); } } // 跑马灯程序3:从中间向两边扩散 void program_3(LED *led, int num) { int mid = num / 2; for (int i = 0; i <= mid; i++) { led[mid - i].state = 1; led[mid + i].state = 1; update_led(led, num); led[mid - i].state = 0; led[mid + i].state = 0; Sleep(100); } } // 跑马灯程序4:随机闪烁 void program_4(LED *led, int num) { srand(time(NULL)); for (int i = 0; i < 10; i++) { int index = rand() % num; led[index].state = 1; update_led(led, num); led[index].state = 0; Sleep(100); } } // 主函数 int main() { LED led[LED_NUM]; init_led(led, LED_NUM); program_1(led, LED_NUM); program_2(led, LED_NUM); program_3(led, LED_NUM); program_4(led, LED_NUM); return 0; } ``` 上述代码实现了四种跑马灯程序,分别为从左到右移动、从右到左移动、从中间向两边扩散、随机闪烁。可以按需求添加更多的跑马灯程序。注意:代码中使用了 Windows 下的 `Sleep()` 函数,如果在其他系统下运行需要修改为相应的函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值