当前位置:文档之家› 8 数码问题-S201307154

8 数码问题-S201307154

8 数码问题-S201307154
8 数码问题-S201307154

基于A 星算法解决8数码问题的编程实现

1.问题描述

8 数码问题又称9 宫问题与游戏“华容道”类似。意在给定3*3棋格的8个格

子内分别放一个符号.符号之间互不相同,余下的一格为空格。并且通常把8 个符号在棋格上的排列顺序称作8 数码的状态。开始时规则给定一个初始状态和一个目标状态并要求被试者对棋格内的符号经过若干次移动由初始状态达到目标状态这个过程中只有空格附近的符号可以朝空格的方向移动且每次只能移动一个符号。

为方便编程和表示,本文中8 个格子内的符号分别取1—8的8 个数字表示.空格用0 表示.并给定8数码的初始状态和和目标状态分别如图1,2所示。

图1 初始状态 图二 目标状态 则要求以图1 为初始状态.通过交换0和0的上、下、左、右四个方位的数字(每次只能和其中一个交换),达到图2 所示目标状态。

2.算法设计

2.1启发式图搜索过程*

核心思想:利用所处理问题的启发信息引导搜索 目的:减少搜索范围,降低问题复杂度. 启发式图搜索算法 A

基本思路:定义一个评价函数 f ,对当前待搜索状态进行评估(既考虑从起始节点到节点 n 的花费,又考虑从节点 n 到达目标节点的费用),然后找出一个最有希望的节点来扩展.

函数形式为:f (n)= g (n)+ h (n) . n 为被评价的节点。 用此函数值来排列 OPEN 表中节点顺序的图搜索算法称为 A 算法. 函数符号说明:

g*(n)、h*(n):表示各部分实际最短路径的耗散值.

f*(n) = g*(n) + h*(n):表示从S 出发,通过节点n 到目标节点 g 的最短路径的耗散值.

f (n)、

g (n) 和

h (n) 为相应路径耗散值的估计值,是一种预测。 A 算法就是利用这种预测,来达到有效搜索的目的.

g (n )可根据搜索历史情况对 g*(n )作出估计,显然有 g (n )>= g*(n ). h (n )则依赖于启发信息,通常称为启发函数,是要对未来扩展的方向作出估计. 算法的伪代码如下:

1. OPEN:=(s),f(s):=g(s)+h(s);

2. LOOP: IF OPEN=( ) THEN EXIT(FAIL);

3 8 2 1 0 5 7 6

4

1 0 2

8 4 3 7 6 5

3. n:=FIRST(OPEN);

4. IF GOAL (n) THEN EXIT(SUCCESS);

5. REMOVE (n, OPEN), ADD(n, CLOSED);

6. EXPAND(n)→(mi),把mi作为n的后继节点添入G,并计算f(n-mi)=g(n-mi)+h(mi);

ADD (mj, OPEN),

IF f(n-mk) < f(mk) THEN f(mk):=f(n-mk),

IF f(n-ml) < f(ml) THEN f(ml):=f(n-ml),

ADD(ml,OPEN);

7. OPEN 中的节点按 f 值从小到大排序;

8. GO LOOP;

算法的说明:

A 算法由一般的图搜索算法改变而成.算法的控制策略是按照 f(n)值递增的顺序对 OPEN 中的元素进行排序,f(n)值小的节点排在前面,大的放在 OPEN 表的后面. 每次扩展节点时,优先选择当前 f(n)值最小的节点来扩展.

2.2八数码问题具体事例

根据任务要求,本文采用A*算法.根据上面A*算法的原理,应该设计合适的启发函数,已经合适的存储结构,以提高效率。

2.2.1存储结构选择

在A*算法中需要用到open表和close表,在A*算法中open表中的结点有严格的顺序,即应按是一个按照f(n)的严格的递增的有序序列,又因为每个结点都要记录当前的状态,以及方便查找到下一个结点,因此我们使用结构体表示问题的状态,同时因为open和close均是一个线性表,而且要便于删除和插入,从而选择链表作为存储结构。

2.2.2结构体中成员变量的选择

因为8数码是用一个3*3的数组表示的,所以这里我们在结构体变量中需要有一个 Cur_S[3][3],来保存当前8数码的状态。为了保证在搜索到目标状态后能够顺利复现寻优路径,我们需要定义一个Prior指针指向该解路径上该节点的父节点。同时因为我们在寻找目标结点的过程中需要对open表进行扩展,从而我们还需要用一个指针Next指针指向扩展结点,当然扩展结点的插入要遵循递增的规则。

为提高程序的运行效率,减少程序扩展结点时候的搜索量,我们需要记录0在Cur_S[3][3]中所处的位置,因此我们使用COL,记录当前空格所在的行号,使用ROW记录当前空格所在的列号。

根据A*算法的定义,当前节点的代价值由估价函数给出即f (n)= g (n)+ h (n) ,在8数码问题中,g(n)是表示当前节点n在搜索树中的深度,h(n)是启发函数,因此在结构体中我增加了Depth表示当前结点的深度,InspireInfo启发信息,CurCost表示当前代价值。

因此结构体TNode定义如下:

2.2.3启发函数的选择

在8 数码问题常用的启发函数为“不在位”的数码个数和数码“不在位”的距离和,在这里,我选择数码“不在位”的距离和作为启发函数。

2.2.4规则库的设计

0 在某一位置时,能选择向左、向右、向上、向下移动中的哪几种策略进行移动,主要取决于当前0所处的行列号,为提高效率新节点要与其祖父节点不同,或其父节点为起始节点。在A*算法中没扩展一个新结点都必须是有效子节点,不为有效子节点不能插入到open表中,具体实现见附件代码中的Expand_TNode函数。

//左移

if(p->ROW<=1) //空格所在列号不小于1,可左移

{

Temp=p->Prior;

if(Temp!=NULL&&Temp->COL==p->COL&&Temp->ROW-1==p->ROW)

; //新节点与其祖父节点相同,无操作

else //新节点与其祖父节点不同或其父节点为起始节点

{

.......(扩展新节点并判断是否加入open 表)//详细代码见源程序

}

}//end 左移

//右移

if(p->ROW<=1) //空格所在列号不大于1,可右移

{

Temp=p->Prior;

if(temp!=NULL&&temp->i_0==p->i_0&&Temp->j_0+1==p->j_0)

; //新节点与其祖父节点相同无操作

else //新节点与其祖父节点不同或其父节点为起始节点

{

......(扩展新节点并判断是否加入open 表)//详细代码见源程序}

}//end 右移

//上移

if(p->COL>=1) //空格所在列号不小于1,可上移

{

Temp=p->Prior;

if(Temp!=NULL&&Temp->COL==p->COL-1&&Temp->ROW==p->ROW)

; //新节点与其祖父节点相同,无操作

else //新节点与其祖父节点不同或其父节点为起始节点

{

......(扩展新节点并判断是否加入open 表)//详细代码见源程序}

}//end 上移

//下移

if(p->COL<=1) //空格所在列号不大于1,可下移

{

Temp=p->Prior;

if(Temp!=NULL&&Temp->COL==p->COL+1&&Temp->ROW==p->ROW)

; //新节点与其祖父节点相同无操作

else //新节点与其祖父节点不同或其父节点为起始节点

{

......(扩展新节点并判断是否加入open 表)//详细代码见源程序}

}//end 下

2.2.5程序流程

其中扩展节点n的具体步骤如下:

首先判断其是否在closed 表已经出现过, 如果出现过并且新节点的代价值比其小,则应将其从closed 表删除,同时将新节点加入到open表。如果没有出现过则判断其是否已经存在于open 表中待扩展,如果出现过并且新节点的代价值比其小,则应将其从open 表删除同时将新节点加入到open 表,如果没有出现过则说明该节点为一个全新的节点转将该节点加入open 表。

3运行结果:

#include "Stdio.h"

#include "Conio.h"

#include "stdlib.h"

#include "math.h"

void Copy_Init_State(struct TNode *q,struct TNode *p);

void Cal_Cur_Cost(int deepth,struct TNode *p);

void Insert_to_open(struct TNode *p);

void Insert_to_closed(struct TNode *p);

void Delete_TNode(struct TNode *name,struct TNode *p);

int JudgeEqualA_B(struct TNode *p1,struct TNode *p2);

struct TNode * Solve_A(struct TNode *p);

void Expand_TNode(struct TNode *p);

struct TNode * Search_A(struct TNode *name,struct TNode *Temp);

void PrintProcessing(struct TNode *p);

void InputData(void);

/* 定义8数码的节点状态*/

typedef struct TNode

{

int Cur_S[3][3]; //当前8数码的状态

int COL; //当前空格所在行号

int ROW; //当前空格所在列号

int CurCost; //当前代价值

int Depth; //当前节点深度

int InspireInfo; //启发信息,采用数码“不在位”距离和

struct TNode *Prior; //指向解路径上该节点的父节点

struct TNode *Next; //指向所在open或closed表中的下一个元素

};

struct TNode *open=NULL; //建立open表指针struct TNode *closed=NULL; //建立closed表指针

int Sum_TNode=0; //用于记录扩展节点总数struct TNode Str;

struct TNode Dir;

int main(void)

{

struct TNode s,*target;

InputData();//输入数据

Copy_Init_State(&Str,&s); //拷贝8数码初始状态,初始化代价值

Cal_Cur_Cost(0,&s);

printf("%s","开始计算!");

target=Solve_A(&s); //求解主程序

if(target) PrintProcessing(target); //输出解路径

else printf("问题求解失败!");

return 0;

}

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

/* 输入原状态和目标状态*/

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

void InputData(void)

{

int i =0,j=0;

printf("%s\n","请输入原状态");

for(i=0;i<3;i++)

for(j=0;j<3;j++)

{

scanf("%d",&Str.Cur_S[i][j]);

if(Str.Cur_S[i][j]==0)

{

Str.COL=i;

Str.ROW=j;

}

}

Str.CurCost=0; //当前代价值

Str.Depth=0; //当前节点深度

Str.InspireInfo=0; //启发信息,采用数码“不在位”距离和

Str.Prior=NULL; //指向解路径上该节点的父节点

Str.Next=NULL; //指向所在open或closed表中的下一个元素printf("%s\n","请输入目标状态");

for(i=0;i<3;i++)

for(j=0;j<3;j++)

{

scanf("%d",&Dir.Cur_S[i][j]);

if(Dir.Cur_S[i][j]==0)

{

Dir.COL=i;

Dir.ROW=j;

}

}

Dir.CurCost=0; //当前代价值

Dir.Depth=0; //当前节点深度

Dir.InspireInfo=0; //启发信息,采用数码“不在位”距离和

Dir.Prior=NULL; //指向解路径上该节点的父节点

Dir.Next=NULL; //指向所在open或closed表中的下一个元素}

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

/* A*算法*/

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

struct TNode * Solve_A(struct TNode *p)

{

struct TNode *n,*Temp;

//int times=0;

Insert_to_open(p); //将str放入open表

while(open!=NULL) //只要open表中还有元素,就继续对代价最小的节点进行扩展

{

n=open; //n指向open表中当前要扩展的元素

Temp=open->Next;

Insert_to_closed(n);

open=Temp;

if(JudgeEqualA_B(n,&Dir)) //当前n指向节点为目标时,跳出程序结束;否则,继续下面的步骤

return n;

Expand_TNode(n); //扩展节点n

// printf("times=%d\n",++times);

}

return NULL;

}

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

/* 生成当前节点n通过走步可以得到的所有状态*/

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

void Expand_TNode(struct TNode *p)

{

struct TNode *Temp,*same;

if(p->ROW>=1) //空格所在列号不小于1,可左移

{

Temp=p->Prior;

if(Temp!=NULL&&Temp->COL==p->COL&&Temp->ROW-1==p->ROW) //新节点与其祖父节点相同

;

else //新节点与其祖父节点不同,或其父节点为起始节点

{

Temp=(struct TNode *)malloc(sizeof(struct TNode)); //给新节点分配空间

Copy_Init_State(p,Temp); //拷贝p指向的节点状态

Temp->Cur_S[Temp->COL][Temp->ROW]=Temp->Cur_S[Temp->COL][Temp->ROW-1]; //空格左移

Temp->Cur_S[Temp->COL][Temp->ROW-1]=0;

Temp->ROW--;

Temp->Depth++;

Cal_Cur_Cost(Temp->Depth,Temp); //修改新节点的代价值

Temp->Prior=p; //新节点指向其父节点

if(same=Search_A(closed,Temp)) //在closed表中找到与新节点状态相同的节点

{

if(Temp->CurCostCurCost) //Temp指向的节点,其代价比closed表中相同状态节点代价小,加入open表

{

Delete_TNode(closed,same); //从closed表中删除与Temp指向节点状态相同的节点

Insert_to_open(Temp);

Sum_TNode++;

}

else;

}

else if(same=Search_A(open,Temp)) //在open表中找到与新节点状态相同的节点

{

if(Temp->CurCostCurCost) //Temp指向的节点,其代价比open表中相同状态节点代价小,加入open表

{

Delete_TNode(open,same); //从open表中删除与Temp指向节点状态相同的节点

Insert_to_open(Temp);

Sum_TNode++;

}

else ;

}

else //新节点为完全不同的新节点,加入open表

{

Insert_to_open(Temp);

Sum_TNode++;

}

}

}//end左移

if(p->ROW<=1) //空格所在列号不大于1,可右移

{

Temp=p->Prior;

if(Temp!=NULL&&Temp->COL==p->COL&&Temp->ROW+1==p->ROW) //新节点与其祖父节点相同

;

else //新节点与其祖父节点不同,或其父节点为起始节点

{

Temp=(struct TNode *)malloc(sizeof(struct TNode)); //给新节点分配空间

Copy_Init_State(p,Temp); //拷贝p指向的节点状态

Temp->Cur_S[Temp->COL][Temp->ROW]=Temp->Cur_S[Temp->COL][Temp->ROW+1]; //空格右移

Temp->Cur_S[Temp->COL][Temp->ROW+1]=0;

Temp->ROW++;

Temp->Depth++;

Cal_Cur_Cost(Temp->Depth,Temp); //修改新节点的代价值

Temp->Prior=p; //新节点指向其父节点

if(same=Search_A(closed,Temp)) //在closed表中找到与新节点状态相同的节点

{

if(Temp->CurCostCurCost) //Temp指向的节点,其代价比closed表中相同状态节点代价小,加入open表

{

Delete_TNode(closed,same); //从closed表中删除与Temp指向节点状态相同的节点

Insert_to_open(Temp);

Sum_TNode++;

}

else;

}

else if(same=Search_A(open,Temp)) //在open表中找到与新节点状态相同的节点

{

if(Temp->CurCostCurCost) //Temp指向的节点,其代价比open表中相同状态节点代价小,加入open表

{

Delete_TNode(open,same); //从open表中删除与Temp指向节点状态相同的节点

Insert_to_open(Temp);

Sum_TNode++;

}

else ;

}

else //新节点为完全不同的新节点,加入open表

{

Insert_to_open(Temp);

Sum_TNode++;

}

}

}//end右移

if(p->COL>=1) //空格所在列号不小于1,上移

{

Temp=p->Prior;

if(Temp!=NULL&&Temp->COL==p->COL-1&&Temp->ROW==p->ROW) //新节点与其祖父节点相同

;

else //新节点与其祖父节点不同,或其父节点为起始节点

{

Temp=(struct TNode *)malloc(sizeof(struct TNode)); //给新节点分配空间

Copy_Init_State(p,Temp); //拷贝p指向的节点状态

Temp->Cur_S[Temp->COL][Temp->ROW]=Temp->Cur_S[Temp->COL-1][Temp->ROW]; //空格上移

Temp->Cur_S[Temp->COL-1][Temp->ROW]=0;

Temp->COL--;

Temp->Depth++;

Cal_Cur_Cost(Temp->Depth,Temp); //修改新节点的代价值

Temp->Prior=p; //新节点指向其父节点

if(same=Search_A(closed,Temp)) //在closed表中找到与新节点状态相同的节点

{

if(Temp->CurCostCurCost) //Temp指向的节点,其代价比closed表中相同状态节点代价小,加入open表

{

Delete_TNode(closed,same); //从closed表中删除与Temp指向节点状态相同的节点

Insert_to_open(Temp);

Sum_TNode++;

}

else;

}

else if(same=Search_A(open,Temp)) //在open表中找到与新节点状态相同的节点

{

if(Temp->CurCostCurCost) //Temp指向的节点,其代价比open表中相同状态节点代价小,加入open表

{

Delete_TNode(open,same); //从open表中删除与Temp指向节点状态相同的节点

Insert_to_open(Temp);

Sum_TNode++;

}

else ;

}

else //新节点为完全不同的新节点,加入open表

{

Insert_to_open(Temp);

Sum_TNode++;

}

}

}//end上移

if(p->COL<=1) //空格所在列号不大于1,下移

{

Temp=p->Prior;

if(Temp!=NULL&&Temp->COL==p->COL+1&&Temp->ROW==p->ROW) //新节点与其祖父节点相同

;

else //新节点与其祖父节点不同,或其父节点为起始节点

{

Temp=(struct TNode *)malloc(sizeof(struct TNode)); //给新节点分配空间

Copy_Init_State(p,Temp); //拷贝p指向的节点状态

Temp->Cur_S[Temp->COL][Temp->ROW]=Temp->Cur_S[Temp->COL+1][Temp->ROW]; //空格下移

Temp->Cur_S[Temp->COL+1][Temp->ROW]=0;

Temp->COL++;

Temp->Depth++;

Cal_Cur_Cost(Temp->Depth,Temp); //修改新节点的代价值

Temp->Prior=p; //新节点指向其父节点

if(same=Search_A(closed,Temp)) //在closed表中找到与新节点状态相同的节点

{

if(Temp->CurCostCurCost) //Temp指向的节点,其代价比closed表中相同状态节点代价小,加入open表

{

Delete_TNode(closed,same); //从closed表中删除与Temp指向节点状态相同的节点

Insert_to_open(Temp);

Sum_TNode++;

}

else;

}

else if(same=Search_A(open,Temp)) //在open表中找到与新节点状态相同的节点

{

if(Temp->CurCostCurCost) //Temp指向的节点,其代价比open表中相同状态节点代价小,加入open表

{

Delete_TNode(open,same); //从open表中删除与Temp指向节点状态相同的节点

Insert_to_open(Temp);

Sum_TNode++;

}

else ;

}

else //新节点为完全不同的新节点,加入open表

{

Insert_to_open(Temp);

Sum_TNode++;

}

}

}//end下移

}

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

/* 添加p指向的节点到open表中*/

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

void Insert_to_open(struct TNode *p)

{

struct TNode *p1,*p2;

p1=open; //初始时p1指向open表首部

p2=NULL;

if(open==NULL) //open表为空时,待插入节点即为open表第一个元素,open指向该元素

{

p->Next=NULL;

open=p;

}

else //open表不为空时,添加待插入节点,并保证open表代价递增的排序

{

while(p1!=NULL&&p->CurCost>p1->CurCost)

{

p2=p1; //p2始终指向p1指向的前一个元素

p1=p1->Next;

}

if(p2==NULL) //待插入节点为当前open表最小

{

p->Next=open;

open=p;

}

else if(p1==NULL) //待插入节点为当前open表最大

{

p->Next=NULL;

p2->Next=p;

}

else //待插入节点介于p2、p1之间

{

p2->Next=p;

p->Next=p1;

}

}

}

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

/* 添加p指向的节点到closed表中*/

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

void Insert_to_closed(struct TNode *p)

{

if(closed==NULL) //closed表为空时,p指向节点为closed表第一个元素,closed指向该元素

{

p->Next=NULL;

closed=p;

}

else //closed表不为空时,直接放到closed表首部

{

p->Next=closed;

closed=p;

}

}

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

/* 在open表或closed表中搜索与Temp指向节点状态相同的节点,*/

/* 返回搜索到的节点地址*/

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

struct TNode * Search_A(struct TNode *name,struct TNode *Temp)

{

struct TNode *p1;

p1=name; //p1指向open表或closed表

while(p1!=NULL)

{

if(JudgeEqualA_B(p1,Temp)) //找到相同的节点,返回该节点地址

return p1;

else

p1=p1->Next;

}

return NULL;

}

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

/* 判断两个节点A、B状态是否相同,相同则返回1,否则返回0 */

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

int JudgeEqualA_B(struct TNode *p1,struct TNode *p2)

{

int i,j,flag;

flag=1;

for(i=0;i<=2;i++)

for(j=0;j<=2;j++)

{

if((p2->Cur_S[i][j])!=(p1->Cur_S[i][j])) { flag=0; return flag; }

else ;

}

return flag;

}

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

/* 从open表或closed表删除指定节点*/

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

void Delete_TNode(struct TNode *name,struct TNode *p)

{

struct TNode *p1,*p2;

p1=NULL;

p2=NULL;

if(name==NULL) //如果name指向的链表为空,则不需要进行删除

return;

else if(JudgeEqualA_B(name,p)&&name->CurCost==p->CurCost) //指定节点为name指向的链表的第一个元素

{

open=name->Next;

name->Next=NULL;

return;

}

else

{

p2=name;

p1=p2->Next;

while(p1)

{

if(JudgeEqualA_B(p1,p)&&p1->CurCost==p->CurCost) //找到指定节点

{

p2->Next=p1->Next;

return;

}

else

{

p2=p1; //p2始终指向p1指向的前一个元素

p1=p1->Next;

}

}

return;

}

}

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

/* 计算某个节点状态的代价值*/

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

void Cal_Cur_Cost(int deepth,struct TNode *p)

{

int i,j,Temp;

Temp=0;

for(i=0;i<=2;i++) //计算所有“不在位”数码的距离和

{

for(j=0;j<=2;j++)

{

switch(p->Cur_S[i][j])

{

case 0: Temp+=abs(i-1)+abs(j-1); break;

case 1: Temp+=abs(i-0)+abs(j-0); break;

case 2: Temp+=abs(i-0)+abs(j-1); break;

case 3: Temp+=abs(i-0)+abs(j-2); break;

case 4: Temp+=abs(i-1)+abs(j-2); break;

case 5: Temp+=abs(i-2)+abs(j-2); break;

case 6: Temp+=abs(i-2)+abs(j-1); break;

case 7: Temp+=abs(i-2)+abs(j-0); break;

case 8: Temp+=abs(i-1)+abs(j-0); break;

}

}

}

p->InspireInfo=Temp;//启发信息,采用数码“不在位”距离和启发信息,采用数码“不在位”距离和

p->CurCost=deepth+p->InspireInfo;//当前代价值

}

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

/* 将p1指向的节点状态拷贝到p2指向的节点中*/

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

void Copy_Init_State(struct TNode *p,struct TNode *q)

{

int i,j;

for(i=0;i<=2;i++)

{

for(j=0;j<=2;j++)

{ q->Cur_S[i][j]=p->Cur_S[i][j]; }

}

q->COL=p->COL;

q->ROW=p->ROW;

q->CurCost=p->CurCost;

q->Depth=p->Depth;

q->InspireInfo=p->InspireInfo;

q->Next=p->Next;

q->Prior=p->Prior;

八位七段数码管动态显示电路设计

八位七段数码管动态显示电路的设计 一七段显示器介绍 七段显示器,在许多产品或场合上经常可见。其内部结构是由八个发光二极管所组成,为七个笔画与一个小数点,依顺时针方向为A、B、C、D、E、F、G与DP等八组发光二极管之排列,可用以显示0~9数字及英文数A、b、C、d、E、F。目前常用的七段显示器通常附有小数点,如此使其得以显示阿拉伯数之小数点部份。七段显示器的脚位和线路图如下图4.1所示( 其第一支接脚位于俯视图之左上角)。 图4.1、七段显示器俯视图 由于发光二极管只有在顺向偏压的时候才会发光。因此,七段显示器依其结构不同的应用需求,区分为低电位动作与高电位动作的两种型态的组件,另一种常见的说法则是共阳极( 低电位动作)与共阴极( 高电位动作)七段显示器,如下图4.2所示。 ( 共阳极) ( 共阴极) 图4.2、共阳极(低电位动作)与共阴极(高电位动作)

要如何使七段显示器发光呢?对于共阴极规格的七段显示器来说,必须使用“ Sink Current ”方式,亦即是共同接脚COM为VCC,并由Cyclone II FPGA使接脚成为高电位,进而使外部电源将流经七段显示器,再流入Cyclone II FPGA的一种方式本实验平台之七段显示器模块接线图如下图4.5所示。此平台配置了八组共阳极之七段显示器,亦即是每一组七段显示器之COM接脚,均接连至VCC电源。而每一段发光二极管,其脚位亦均与Cyclone II FPGA接连。四位一体的七段数码管在单个静态数码管的基础上加入了用于选择哪一位数码管的位选信号端口。八个数码管的a、b、c、d、e、f、g、h、dp都连在了一起,8个数码管分别由各自的位选信号来控制,被选通的数码管显示数据,其余关闭。 图4.5、七段显示器模块接线图 七段显示器之常见应用如下 ?可作为与数值显示相关之设计。 ?电子时钟应用显示 ?倒数定时器 ?秒表 ?计数器、定时器 ?算数运算之数值显示器

七段数码管显示

七段数码管显示设计报告 目录 一、设计任务 二、题目分析与整体构思 三、硬件电路设计 四、程序设计 五、心得体会

一.设计任务 数码的显示方式一般有三种:第一种是字型重叠式;第二种是分段式;第三种是点阵式。目前以分段式应用最为普遍,主要器件是七段发光二极管(LED)显示器。它可分为两种,一是共阳极显示器(发光二极管的阳极都接在一个公共点上),另一是共阴极显示器(发光二极管的阳极都接在一个公共点上,使用时公共点接地)。 数码管动态扫描显示,是将所用数码管的相同段(a~g 和p)并联在一起,通过选位通 信号分时控制各个数码管的公共端,循环依次点亮各个数码管。当切换速度足够快时,由于人眼的“视觉暂留”现象,视觉效果将是数码管同时显示。 根据七段数码管的显示原理,设计一个带复位的七段数码管循环扫描程序,本程序需要着重实现两部分: 1. 显示数据的设置:程序设定4 位数码管从左至右分别显示1、2、3、4; 2. 动态扫描:实现动态扫描时序。 利用EXCD-1 开发板实现七段数码管的显示设计,使用EXCD-1 开发板的数码管为四位共阴极数码管,每一位的共阴极7 段数码管由7 个发光LED 组成,7 个发光LED 的阴极连接在一起,阳极分别连接至FPGA相应引脚。四位数码管与FPGA 之间通过8 位拨码开关(JP1)进行连接。 二.题目分析与整体构思 使用EXCD-1 开发板的数码管为四位共阴极数码管,每一位的共阴极7 段数码管由7 个发光LED 组成,呈“”字状,7 个发光LED 的阴极连接在一起,阳极分别连接至FPGA 相应引脚。SEG_SEL1、SEG_SEL2、SEG_SEL3 和SEG_SEL4 为四位7 段数码管的位选择端。当其值为“1”时,相应的7 段数码管被选通。当输入到7 段数码管SEG_A~ SEG_G 和SEG_DP 管脚的数据为高电平时,该管脚对应的段变亮,当输入到7 段数码管 SEG_A~SEG_G 和SEG_DP 管脚的数据为低电平时,该管脚对应的段变灭。该四位数码管与FPGA 之间通过8 位拨码开关(JP1)进行连接,当DIP 开关全部拨到上方时(板上标示为:7SEGLED),FPGA 的相应IO 引脚和四位7 段数码管连接,7 段数码管可以正常工作;当DIP 开关全部拨到下方时(板上标示为:EXPORT5),FPGA 的相应IO引脚与7 段数码管断开,相应的FPGA 引脚用于外部IO 扩展。 注意:无论拨码开关断开与否,FPGA 的相应IO 引脚都是与外部扩展接口连接的,所 以当正常使用数码管时,不允许在该外部扩展接口上安装任何功能模块板。 数码管选通控制信号分别对应4 个数码管的公共端,当某一位选通控制信号为高电平时,其对应的数码管被点亮,因此通过控制选通信号就可以控制数码管循环依次点亮。一个数码管稳定显示要求的切换频率要大于50Hz,那么4 个数码管则需要50×4=200Hz 以上的切换频率才能看到不闪烁并且持续稳定显示的字符。 三.硬件电路设计 设计结构图如下:

《一位LED数码管显示0-9》

成都理工大学工程技术学院 单片微机原理及应用课程设计《一位LED数码管显示0-9》 学生姓名: 学号: 专业:

班级: 指导教师: 完成日期: 目录 一实验目的与任务 (2) 二实验要求 (2) 三实验内容 (2) 四元器件清单 (2) 五LED数码管的结构及工作原理 (2) 六关于PLC控制LDE介绍 (4) 七原理图绘制说明 (5) 八流程图绘制以及说明 (9)

九电路原理图与仿真 (10) 十源程序 (12) 十一心得体会 (12) 十二参考文献 (13) 一、实验与任务 结合实际情况,编程设计、布线、程序调试、检查与运行,完成一个与接近实际工程项目的课题,以培养学生的实际操作能力,适应生产一线工作的需要。做到能检查出错误,熟练解决问题;对设备进行全面维修。通过实训对PLC的组成、工作原理、现场调试以及基于网络化工作模式的基本配置与应用等有一个一系列的认识和提高。 利用51单片机、1个独立按键及1位7段数码管等器件,设计一个单片机输入显示系统,要求每按一下独立按键数码管显示数据加1(数码管初始值设为0,计到9后再加1 ,则数码管显示0)。 本次设计采用12MHz的晶体振荡器为单片机提供振荡周期,外加独立按键,复位电路和显示电路组成。 二、实验要求 1、了解七段LED数码管的结构、分类以及数码管的显示码。 2、学习1位LED数码管静态显示与动态显示的编程方法。

3、掌握可编程序控制器技术应用过程中的一些基本技能。 4、了解可编程控制器的装备、调试的全过程。 三、实验内容 1、练习设计、连接、调试控制电路; 2、学习PLC程序编程; 四、元器件清单 从PROTUES库中选择元器件 (1)AT89C51;单片机。 (2)RES、RX8;电阻、8排阻。 (3)7SEG-COM-CAT-BLUE;带公共端共阴极七段蓝色数码管。 (4)CAP/CAP-ELEC;电容、电解电容。 (5)CRYSTAL:晶振。 五、LED数码管的结构及工作原理 led数码管(LED Segment Displays)是由多个发光二极管封装在一起组成“8”字型的器件,引线已在内部连接完成,只需引出它们的各个笔划,公共电极。led数码管常用段数一般为7段有的另加一个小数点,还有一种是类似于3位“+1”型。位数有半位0,1,2,3,4,5,6,8,10位等等....,led数码管根据LED的接法不同分为共阴和共阳两类,了解LED的这些特性,对编程是很重要的,因为不同类型的数码管,除了它们的硬件电路有差异外,编程方法也是不同的。图2是共阴和共阳极数码管的内部电路,它们的发光原理是一样的,只是它们的电源极性不同而已。颜色有红,绿,蓝,黄等几种。led数码管广泛用于仪表,时钟,车站,家电等场合。选用时要注意产品尺寸颜色,功耗,亮度,

数码管显示动态数字 单片机报告

目录 一、设计题目 (2) 二、设计目的 (2) 2.1设计目的要求 (2) 2.2 系统设计意义 (2) 三、系统硬件图 (3) 四、程序流程图 (3) 五、系统说明与分析 (4) 5.1系统主要组成部分 (4) 5.2 单片机最小系统部分 (4) 5.2.1 MCS-51系列单片机概述 (4) 5.2.2 MCS-51系列单片机的并行I/O口 (5) 5.2.3 MCS-51系列单片机的工作方式和时序 (8) 5.3串行转并行部分 (10) 5.3.1 74ls164的概述 (10) 5.3.2 74ls164的功能 (15) 5.4数码显示部分 (16) 5.4.1概述 (16) 5.4.2 LED数码管引脚结构 (16) 5.4.3 LED数码管显示原理 (17) 5.4.4 LED数码管的驱动方式 (17) 5.5电路板的制作 (18) 5.6 系统连线说明分析 (19) 六、源程序 (20) 七、总结 (22) 八、参考文献 (23)

一、设计题目 通过51系列单片机的串行口和74ls164显示0~9十个数字。 二、设计目的 该单片机最小应用系统设计目的及要求如下: 2.1设计目的要求 1、通过本次实验,掌握单片机串行口的扩展功能; 2、通过对单片机的使用和编程,了解单片机的应用编程; 3、搭建单片机最小应用系统,进一步加深对单片机应用的理解,提高处理实际问题的能力和独立分析思考的能力; 4、掌握单片机汇编编程技术中的设计和分析方法; 5、学会使用并熟练掌握电路绘制软件Protel99SE(或DXP); 6、掌握电路图绘制及PCB图布线技巧。 2.2 系统设计意义 1、在系统掌握单片机相应基础知识的前提下,熟悉单片机最小应用系统的设计方法及系统设计的基本步骤。 2、完成所需单片机最小应用系统原理图设计绘制的基础上完成系统的电路图设计。 3、完成系统所需的硬件设计制作,在提高实际动手能力的基础上进一步巩固所学知识。 4、进行题目要求功能基础上的软件程序编程,会用相应软件进行程序调试和测试工作。 5、用AT89S51,74ls164设计出题目所要求的数字显示,实现循环显示,并针对实际设计过程中软、硬件设计方面出现的问题提出相应解决办法。 6、通过单片机应用系统的设计将所学的知识融会贯通,锻炼独立设计、制作和调试单片机应用系统的能力;领会单片机应用系统的软、硬件调试方法和系统的研制开发过程,为进一步的科研实践活动打下坚实的基础。

6位7段LED数码管显示

目录 1. 设计目的与要求..................................................... - 1 - 1.1 设计目的...................................................... - 1 - 1.2 设计环境...................................................... - 1 - 1.3 设计要求...................................................... - 1 - 2. 设计的方案与基本原理............................................... - 2 - 2.1 6 位 8 段数码管工作原理....................................... - 2 - 2.2 实验箱上 SPCE061A控制 6 位 8 段数码管的显示................... - 3 - 2.3 动态显示原理.................................................. - 4 - 2.4 unSP IDE2.0.0 简介............................................ - 6 - 2.5 系统硬件连接.................................................. - 7 - 3. 程序设计........................................................... - 8 - 3.1主程序......................................................... - 8 - 3.2 中断服务程序.................................................. - 9 - 4.调试............................................................... - 12 - 4.1 实验步骤..................................................... - 12 - 4.2 调试结果..................................................... - 12 - 5.总结............................................................... - 14 - 6.参考资料........................................................... - 15 - 附录设计程序汇总.................................................... - 16 -

实验四八位七段数码管动态显示电路的设计

八位七段数码管动态显示电路的设计 一、实验目的 1、了解数码管的工作原理。 2、学习七段数码管显示译码器的设计。 3、学习VHDL的CASE语句及多层次设计方法。 二、实验原理 七段数码管是电子开发过程中常用的输出显示设备。在实验系统中使用的是两个四位一体、共阴极型七段数码管。其单个静态数码管如下图4-4-1所示。 图4-1 静态七段数码管 由于七段数码管公共端连接到GND(共阴极型),当数码管的中的那一个段被输入高电平,则相应的这一段被点亮。反之则不亮。共阳极性的数码管与之相么。四位一体的七段数码管在单个静态数码管的基础上加入了用于选择哪一位数码管的位选信号端口。八个数码管的a、b、c、d、e、f、g、h、dp都连在了一起,8个数码管分别由各自的位选信号来控制,被选通的数码管显示数据,其余关闭。 三、实验内容 本实验要求完成的任务是在时钟信号的作用下,通过输入的键值在数码管上显示相应的键值。在实验中时,数字时钟选择1024HZ作为扫描时钟,用四个拨动开关做为输入,当四个拨动开关置为一个二进制数时,在数码管上显示其十六进制的值。 四、实验步骤 1、打开QUARTUSII软件,新建一个工程。 2、建完工程之后,再新建一个VHDL File,打开VHDL编辑器对话框。 3、按照实验原理和自己的想法,在VHDL编辑窗口编写VHDL程序,用户可参照光 盘中提供的示例程序。 4、编写完VHDL程序后,保存起来。方法同实验一。

5、对自己编写的VHDL程序进行编译并仿真,对程序的错误进行修改。 6、编译仿真无误后,根据用户自己的要求进行管脚分配。分配完成后,再进行全编译 一次,以使管脚分配生效。 7、根据实验内容用实验导线将上面管脚分配的FPGA管脚与对应的模块连接起来。 如果是调用的本书提供的VHDL代码,则实验连线如下: CLK:FPGA时钟信号,接数字时钟CLOCK3,并将这组时钟设为1024HZ。 KEY[3..0]:数码管显示输入信号,分别接拨动开关的S4,S3,S2,S1。 LEDAG[6..0]:数码管显示信号,接数码管的G、F、E、D、C、B、A。 SEL[2..0]:数码管的位选信号,接数码管的SEL2、SEL1、SEL0。 8、用下载电缆通过JTAG口将对应的sof文件加载到FPGA中。观察实验结果是否与 自己的编程思想一致。 五、实验现象与结果 以设计的参考示例为例,当设计文件加载到目标器件后,将数字信号源模块的时钟选择为1464HZ,拨动四位拨动开关,使其为一个数值,则八个数码管均显示拨动开关所表示的十六进制的值。

7段数码管的使用(个人总结)

七段数码管引脚图 图1 共阳1位数码管引脚图图2 段号实际位置 数码管使用条件: A)段、小数点上加限流电阻 B)使用电压:段_根据发光颜色决定小数点_根据发光颜色决定 C)使用电流: 静态:总电流 80mA(每段 10mA) 动态:平均电流 4-5mA 峰值电流: 100mA 数码管使用注意事项说明: A)数码管表面不要用手触摸,不要用手去弄引角; B)焊接温度:260度焊接时间:5S C)表面有保护膜的产品,可以在使用前撕下来。

实际使用说明: A)7段数码管可以分为共阳极与共阴极两种,共阳极就是把所有LED的阳极连接到共同接点com,而每个LED的阴极分别为a、b、c、d、e、f、g及dp(小数点);共阴极则是把所有LED的阴极连接到共同接点com,而每个LED的阳极分别为a、b、c、d、e、f、g及dp(小数点),如下图所示。图中的8个LED分别与上面那个图中的A~DP各段相对应,通过控制各个LED的亮灭来显示数字。 B)对于单个数码管,从它的正面看进去,左下角那个脚为1脚,以逆时针方向依次为1~10脚。注意,3脚和8脚是连通的,这两个都是公共脚。 C)对于四位数码管,内部的4个数码管共用a~dp这8根数据线,有4公共端,共有12个引脚。引脚排列从正面看进去,依然是从左下角的那个脚(1脚)开始,以逆时针方向依次为1~12脚(反面标有1脚和12脚,从1脚顺时针数到12脚,便是1~12脚)。 图3 4位共阳数码管引脚图

D)4位管典型用法 (1)SM接VCC (2)实际接线时,找准com端,Data端怎么方便怎么连接 (3)驱动com1,逐个驱动D0~D7口,观察对应亮起的段号,做一一对应 (4)根据实际数字、字母的段组成,编写8位Data端的2位16进制编码

7段数码管显示电路

4.4 显示模块 4.4.1 7段数码管的结构与工作原理 7段数码管一般由8个发光二极管组成,其中由7个细长的发光二极管组成 数字显示,另外一个圆形的发光二极管显示小数点。 当发光二极管导通时,相应的一个点或一个笔画发光。控制相应的二极管导通,就能显示出各种字符,尽管显示的字符形状有些失真,能显示的数符数量也有限,但其控制简单,使有也方便。发光二极管的阳极连在一起的称为共阳极数码管,阴极连在一起的称为共阴极数码管,如图4.9所示。 4.4.2 7段数码管驱动方法 发光二极管(LED 是一种由磷化镓(GaP )等半导体材料制成的,能直接将电能转变成光能的发光显示器件。当其内部有一一电流通过时,它就会发光。 7段数码管每段的驱动电流和其他单个LED 发光二极管一样,一般为5~10mA ;正向电压随发光材料不同表现为1.8~2.5V 不等。 7段数码管的显示方法可分为静态显示与动态显示,下面分别介绍。 (1) 静太显示 所谓静态显示,就是当显示某一字符时,相应段的发光二极管恒定地寻能可截止。这种显示方法为每一们都需要有一个8位输出口控制。对于51单片机,可以在并行口上扩展多片锁存74LS573作为静态显示器接口。 静态显示器的优点是显示稳定,在发光二极管导通电注一定的情况下显示器的亮度高,控制系统在运行过程中,仅仅在需要更新显示内容时,CPU 才执行一次显示更新子程序,这样大大节省了CPU 的时间,提高了CPU 的工作效率;缺点是位数较多时,所需I/O 口太多,硬件开销太大,因此常采用另外一种显示方式——动态显示。

(2)动态显示 所谓动态显示就是一位一位地轮流点亮各位显示器(扫描),对于显示器的每一位而言,每隔一段时间点亮一次。虽然在同一时刻只有一位显示器在工作(点亮),但利用人眼的视觉暂留效应和发光二极管熄 灭时的余辉效应,看到的却是多个字符“同时”显示。显示器亮度既与点亮时的导通电流有关,也与点亮时间和间隔时间的比例有关。调整电流和时间参烽,可实现亮度较高较稳定的显示。若显示器的位数不大于8位,则控制显示器公共极电位只需一个8位I/O 口(称为扫描口或字位口),控制各位LED 显示器所显示的字形也需要一个8位口(称为数据口或字形口)。 动态显示器的优点是节省硬件资源,成本较低,但在控制系统运行过程中,要保证显示器正常显示,CPU 必须每隔一段时间执行一次显示子程序,这占用了CPU 的大量时间,降低了CPU 工作效率,同时显示亮度较静态显示器低。 综合以上考虑,由于温度显示为精确到小数点后两位,故只需4个数码管,又考虑到CPU 工作效率与电源效率,本毕业设计采用静态显示。为共阳极显示。 4.4.3 硬件编码 动74LS47是一款BCD 码转揣为7段输出的集成电路芯片,利用它可以直接驱动共阳 极的7段数码管。它的引脚分部和真值表分别下图。

单片机数码管静态显示实验程序(汇编)

单片机数码管静态显示实验程序 org 00h num equ p0 ;p0口连接数码管 clr p2.0 ; mov dptr ,#tab clr a mov r2,#0 loop: movc a,@a+dptr mov num ,a acall delay_200ms inc r2 mov a,r2 cjne r2,#15, loop mov r2,#0 clr a ajmp loop tab : DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,88H,83H,0C6H,0A1H,86H,8EH delay_200ms: mov r3,#20 delay: acall delay_10ms djnz r3,delay ret ;;;;;;;;;;;;;;;; 非中断精确1MS定时程序;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; delay_1ms: MOV R7 ,#249 signed: ;循环部分4机器周期 nop nop djnz R7 ,signed ret ;返回指令2机器周期 ;2+249*4+2=1000us 可以精确定时1MS,假设外部晶振是12M

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 非中断精确10MS定时程序;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov r6,#9 ;2个机器周期用2us delay_10ms_sined: ;9次循环共用9(1ms+4us)=9036us acall delay_1ms djnz r6,delay_10ms_sined MOV r6 ,#240 ;2个机器中期用2us signed_10ms : ;循环部分4机器周期共240次 nop nop djnz r6 ,signed_10ms ret ;返回指令要2us ;2us+9036us+240*4us+2us = 10ms 即可精确定时10ms ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 非中断精确定时1s ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; delay_1s: mov r5,#99 ;两个机器周期2us delay_1s_signed: ;循环指令周期为4us,加上延时10ms ;(10ms+4us)*99 = 990.396ms acall delay_10ms djnz r5,delay_1s_signed mov r5 ,#9 ;两个机器周期2us signed_1s: ;循环指令周期为4us,加上延时1ms ;(1ms+4us)*9 = 9ms+36us acall delay_1ms djnz r5 ,signed_1s mov r5 ,# 140 ;机器周期2us signed_1s_: ;一次循环4us共有140次。140us*4 = 560us nop nop djnz r5,signed_1s_ ret ;2us ;2us+990ms+396us+2us+9ms+36us+2us+560us+2us = 999ms+1000us = 1s end

数码管动态显示数字

/***********************用译码器*******************************************/ #include #define GPIO_DIG P0 sbit LSA=P2^0; sbit LSB=P2^1; sbit LSC=P2^2; unsigned char code DIG_CODE[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, 0x77,0x7c,0x39,0x5e,0x79,0x71};//共阴极数码管字型码0~F void Delay10ms(unsigned int c) //误差0us { unsigned char a, b; for (;c>0;c--) { for (b=38;b>0;b--) { for (a=130;a>0;a--); } } } void main() { unsigned char i=0; P2=0x00; //位显示 while(1) { GPIO_DIG=DIG_CODE[i++]; //段显示 Delay10ms(100); //55us GPIO_DIG=0x00;//消隐 P2=(P2+1)%8; if(i==8) i=0; } } /*******************不用译码器****************************************/ #include //--定义使用的IO口--// #define GPIO_DIG P0 //段选 #define GPIO_PLACE P1 //位选 //--定义全局变量--// unsigned char code DIG_PLACE[8] = {

8位8段led数码管动态扫描显示 (1)

项目名称:8位8段LED数码管动态扫描显示班级:09电二姓名:解健学号:09020313 一.实验目的 1.掌握数码管动态扫描显示原理及实现方法。 2.掌握动态扫描显示电路驱动程序的编写方法。 二.实验电路 三.元器件 元器件编号元器件名称说明 U2 7445 集电极开路的BCD十进制译码器/驱动器U3 74HC245 8位总线驱动器 U1 AT89C52 AT89C52单片机 RP1 RESPACK8 具有公共端的排电阻 7SEG-MPX8-CC-BLUE 共阴极8位7段LED蓝色显示器四.实验步骤 第一步:先在Proteus软件中设计仿真电路原理图。 第二步:再在Keil C51软件中编写且编译程序,程序后缀必须是.c。然后在打开的“Option for Target‘Target 1’”选项卡,“Target”标签下频率设置为“11.0592”,“Output”标签下,将“Creat HEX File”项打勾选中,设置生成一个.hex文件。 第三步:接着将.hex文件导入原理图中U1芯片。双击U1,打开Edit Component对话框,选择生成的hex文件。 第四步:最后观察设计的电路图是否能得到预想的效果,若不能,进行检查,找到毛病且纠正。

流程图 实验现象: 显示器点亮所有段,持续约1s ,然后灭显示器,持续2s,最后显示“hello-93”,保持。 附:程序 #include #include #define TRUE 1 #define dataPort P0 #define ledConPort P2 unsigned char code ch[8]={0x76,0x79,0x38,0x38,0x3f,0x40,0x6f,0x4f}; void time(unsigned int ucMs); void main(void) N N N N Y Y Y Y 开始 选择段 点亮所有位 Counter=0 I=0 I++ I<30 灭显示器 延时 选择段 按数值点亮位 Counter=0 延时 Counter<8 停止 结束 Counter++ Counter<8 Counter++ 延时

单个数码管静态显示教案

单个数码管静态显示公开课教案 主讲老师杨镇彬授课班级13电子B2 日期2014.11.11 教学目标:1、理解数码管显示控制原理; 2、掌握单个数码管静态显示的程序;并能修改程序; 3、能使用模拟软件模拟实验效果。 重点难点:1、数码管静态显示原理; 2、数码管显示控制的主程序。 教学过程时 间 一、复习ORG MOV AJMP SJMP DJNZ CLR RET END 4 二、导入在我们生活中能经常见到LED数码管的应用实例,如电饭煲、电磁炉、洗 衣机、数码万年历等等,这些数码管都是由单片机控制的,那么如何控制数码 管显示的呢? 1 三、七段LED数码管内部结构 有a、b、c、d、e、f、g七个笔画,第八位为小数点dp,分为共阳、共阴 两大类。 3

四、显示原 理 以共阴极为例(控制正极,高电平有效)9 五、电气原 理图分析 3 六、练习1猜猜显示的数字是多少? MOV P0,# 0000 0110 B 1 MOV P0,# 0101 1011 B 2 MOV P0,# 0111 1111 B 8 请问要显示数字7的话,需要传送什么数值给P0端口? 6 七、单个数码管显示MAIN: CLR P2.0;设置低电平,接通负极 MOV A,#00000110B;储存控制信号 MOV P0,A;传送控制信号 LCALL DELAY;调用延时子程序 SJMP MAIN;跳回主程序 8

主程序 八、完整程序ORG 0000H AJMP MAIN ORG 0100H MAIN:CLR P2.0 MOV A,#00000110B MOV P0,A SJMP MAIN END 1 九、软件模 拟实验 1、显示数字1; 2 十、学生 操作 叫学生上讲台操作(修改程序) 2

8位7段数码管字符

显示0,#01000000B 40H 显示1,#01111001B 79H 显示2,#00100100B 24H 显示3,#00110000B 30H 显示4,#00011001B 19H 显示5,#00010010B 12H 显示6,#00000010B 02H 显示7,#01011000B 58H 显示8,#00000000B 00H 显示9,#00010000B 10H 显示A,#00001000B 08H 显示B,#00000011B 03H 显示C,#01000110B 46H 显示D,#00100001B 21H 显示E,#00000110B 06H 显示F,#00001110B 0EH 数字0-9: 40H,79H,24H,30H,19H,12H,02H,58H,00H,10H 字母A-F: 08H,03H,46H,21H,06H,0EH (小数点不亮) 显示0,#11000000B 0C0H 显示1,#11111001B 0F9H 显示2,#10100100B 0A4H 显示3,#10110000B 0B0H 显示4,#10011001B 99H 显示5,#10010010B 92H 显示6,#10000010B 82H 显示7,#11011000B 0D8H 显示8,#10000000B 80H 显示9,#10010000B 90H 显示A,#10001000B 88H 显示B,#10000011B 83H 显示C,#11000110B 0C6H 显示D,#10100001B 0A1H 显示E,#10000110B 86H 显示F,#10001110B 8EH 数字0-9: 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0D8H,80H,90H

4位7段数码管驱动电路设计要求

4位7段数码管驱动电路 图1 开发板电路原理图 信号说明

1. iRST_N(异步复位) 当iRST_N信号为低时,Seg7_Driver模块中的所有寄存器异步复位为初值。 2. iCLK 模块的输入时钟40MHz。 3. iSeg_Val[15:0] 7段数码管输入二进制值,0x0~0xF iSeg_Val[15:12],左侧第一位7段数码管的值。 iSeg_Val[11: 8],左侧第两位7段数码管的值。 iSeg_Val[ 7: 4],左侧第三位7段数码管的值。 iSeg_Val[ 3: 0],左侧第四位7段数码管的值。 4. iDot_Val[3:0] 各位7段数码管小数点的显示,值为1表示显示小数点,0表示不显示小数点。 iDot_Val[3],左侧第一位7段数码管的小数点。 iDot_Val[2],左侧第两位7段数码管的小数点。 iDot_Val[1],左侧第三位7段数码管的小数点。 iDot_Val[0],左侧第四位7段数码管的小数点。 5. oDisplay[7:0] 7段数码管的数据信号。4位7段数码管共用数据信号。7段数码管为共阳极连接,各段数据线为0时,对应段发光。 6. oDis_En[3:0] 各位7段数码管的使能信号,低有效。

oDis_En[3],左侧第一位7段数码管的使能信号。 oDis_En[2],左侧第两位7段数码管的使能信号。 oDis_En[1],左侧第三位7段数码管的使能信号。 oDis_En[0],左侧第四位7段数码管的使能信号。 建议的分块: 将整个驱动电路分成Seg7_Ctrl模块与Seg7_Hex2seg模块 Seg7_Ctrl模块负责产生数码管动态显示的控制信号oDis_En的时序 Seg7_Hex2Seg模块负责将二进制值转换成数据码管显示的数据值,包括小数点的值。 注意点: 1. 动态显示过程是利用人眼的视觉残留现象来实现的,应选择适当的数码管扫描频率。可先 选择数码管的扫描显示的刷新率为125Hz(8ms),即每位数码管用2ms。 2. 完成基本功能后,可实验改变刷新率,观察数码管显示的效果,并思考原因。 3. 如果要使得数码管能够显示,A,b,C,n,o等其他字符,模块应该作怎样的修改?

BCD七段数码管显示译码器电路

BCD七段数码管显示译码器电路 7段数码管又分共阴和共阳两种显示方式。如果把7段数码管的每一段都等效成发光二极管的正负两个极,那共阴就是把abcdefg这7个发光二极管的负极连接在一起并接地;它们的7个正极接到7段译码驱动电路74LS48的相对应的驱动端上(也是abcdefg)!此时若显示数字1,那么译码驱动电路输出段bc为高电平,其他段扫描输出端为低电平,以此类推。如果7段数码管是共阳显示电路,那就需要选用74LS47译码驱动集成电路。共阳就是把abcdefg的7个发光二极管的正极连接在一起并接到5V电源上,其余的7个负极接到74LS47相应的abcdefg输出端上。无论共阴共阳7段显示电路,都需要加限流电阻,否则通电后就把7段译码管烧坏了!限流电阻的选取是:5V电源电压减去发光二极管的工作电压除上10ma到15ma得数即为限流电阻的值。发光二极管的工作电压一般在1.8V--2.2V,为计算方便,通常选2V即可!发光二极管的工作电流选取在10-20ma,电流选小了,7段数码管不太亮,选大了工作时间长了发光管易烧坏!对于大功率7段数码管可根据实际情况来选取限流电阻及电阻的瓦数! 发光二极管(LED)由特殊的半导体材料砷化镓、磷砷化镓等制成,可以单独使用,也可以组装成分段式或点阵式LED显示器件(半导体显示器)。分段式显示器(LED数码管)由7条线段围成8型,每一段包含一个发光二极管。外加正向电压时二极管导通,发出清晰的光,有红、黄、绿等色。只要按规律控制各发光段的亮、灭,就可以显示各种字形或符号。图4 - 17(a)是共阴式LED数码管的原理图,图4-17(b)是其表示符号。使用时,公共阴极接地,7个阳极a~g由相应的BCD七段译码器来驱动(控制),如图4 - 17(c)所示。 BCD七段译码器的输入是一位BCD码(以D、C、B、A表示),输出是数码管各段的驱动信号(以F a~F g表示),也称4—7译码器。若用它驱动共阴LED数码管,则输出应为高有效,即输出为高(1)时,相应显示段发光。例如,当输入8421码DCBA=0100时,应显示,即要求同时点亮b、c、f、g段,熄灭a、d、e段,故译码器的输出应为F a~F g=0110011,这也是一组代码,常称为段码。同理,根据组成0~9这10个字形的要求可以列出8421BCD七段译码器的真值表,见表4 - 12(未用码组省略)。

静态数码管显示程序

/************************************************************************** ***** * 实验名: 静态数码管实验 * 使用的IO : 数码管使用P0,键盘使用P3.0、P3.1、P3.2、P3.3 * 实验效果: 按下K1键,显示0,按下K2键,显示9,按下K3键,显示减1,按下K4键, *显示加1。 * 注意:由于P3.2口跟红外线共用,所以做按键实验时为了不让红外线影响实验 *效果,最好把红外线先取下来。 *************************************************************************** ****/ #include #include #define GPIO_DIG P0 sbit LSA=P2^2; sbit LSB=P2^3; sbit LSC=P2^4; sbit K1=P3^1; sbit K2=P3^0; sbit K3=P3^2; sbit K4=P3^3; unsigned char code DIG_CODE[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//显示0~9的值 void Delay10ms(); //延时10ms /************************************************************************** ***** * 函数名: main * 函数功能: 主函数 * 输入: 无 * 输出: 无 *************************************************************************** ****/ void main(void) { unsigned int i,j; LSA=0; LSB=0;

7段数码管实验报告

EDA 实验报告 实验名称: 7段数码管控制接口学院:信息工程学院 专业: 11级电子信息工程2班年级、班: 2009级2班 学生姓名:王璐 指导教师:郭华 2014 年 6 月24 日

7段数码管控制接口 一、实验要求。 用设计一个共阴7 段数码管控制接口,要求:在时钟信号的控制下,使 6 位数码管动态刷新显示0—F,其中位选信号为8-3 编码器编码输出。 二、实验内容。 在实验仪器中,8 位7 段数码显示的驱动电路已经做好,并且其位选信(SEL[7..0])为一3-8 译码器的输出,所以我们在设计7 段数码管控制接口时,其位选信号输出必须经8-3编码。 显示控制器的引脚图如图40-1: 图1 图中CP 为时钟输入端,SEGOUT[7..0]为段驱动输出;SELOUT[2..0]为位选信号输出;NUMOUT[3..0]为当前显示的数据输出。 图40-2 7段显示控制器仿真波形图 从图40-2可以看出,6位数码管是轮流点亮的,我们以NUMOUT=1 这段波形为参考:当SELOUT为000时,点亮第一位显示器,显示的数字为1,同时,NUMOUT 输出的数据也为“0001”。同理,当SELOUT 为001 时,点亮第二位显示器,显示数字为1,直到 6 位显示器全都显示完毕,等待进入下一个数字的显示。 同时,还有一个问题不可忽视,位扫描信号的频率至少需要多少以上,才能使显示器不闪烁?简单的说,只要扫描频率超过眼睛的视觉暂留频率24HZ以上就可以达到点亮单个显示,却能享有6个同时显示的视觉效果,而且显示也不闪烁。当我们输入频率为5MHZ时,我们通过加法计数器来产生一个约300HZ 的信号,并且由它来产生位选信号,请参考下面程序段:

实验四 数码管静态显示

实验四数码管静态显示 一、实验目的 1.熟练掌握单片机定时器的原理和应用方法。 2.了解数码管的原理,掌握数码管的真值表的计算方法。 二、实验内容 通过对单片机编程来实现数码管静态显示。 三、实验知识点 3.1定时器的初步认识 时钟周期:时钟周期T是时序中最小的时间单位具体计算的方法就是1/时钟源,我们KST-51单片机开发板上用的晶振是11.0592M,那么对于我们这个单片机系统来说,时钟周期=1/11059200秒。 机器周期:我们的单片机完成一个操作的最短时间。机器周期主要针对汇编语言而言,在汇编语言下程序的每一条语句执行所使用的时间都是机器周期的整数倍,而且语句占用的时间是可以计算出来的,而C语言一条语句的时间是不可计算的。51单片机系列,在其标准架构下一个机器周期是12个时钟周期,也就是12/11059200秒。 定时器和计数器。定时器和计数器是单片机内部的同一个模块,通过配置SFR(特殊功能寄存器)可以实现两种不同的功能。 顾名思义,定时器就是用来进行定时的。定时器内部有一个寄存器,我们让它开始计数后,这个寄存器的值每经过一个机器周期就会加1一次,因此,我们可以把机器周期理解为定时器的计数周期。我们的秒表,每经过一秒,数字加1,而这个定时器就是每过一个机器周期的时间,也就是12/11059200秒,数字加1。 3.2 定时器的寄存器描述 标准的51里边只有定时器0和定时器1这两个定时器,现在很多单片机也有多个定时器的,在这里我们先讲定时器0和1。那么我前边提到过,对于单片机的每一个功能模块,都是由他的SFR,也就是特殊功能寄存器来控制。而和定时器有关的特殊功能寄存器,有TCON和TMOD,定时值存储寄存器。 a)定时值存储寄存器 表4-1中的寄存器,是存储计数器的计数值的,TH0/TL0用于T0, TH1/TL1用于 T1。 表4-1 定时值存储寄存器 表4-2 TCON--定时器/计数器控制寄存器的位分配(地址:88H) 表4-3 TCON--定时器/计数器控制寄存器的位描述

8位数码管动态显示电路设计.

电子课程设计 — 8位数码管动态显示电路设计 学院:电子信息工程学院 专业、班级: 姓名: 学号: 指导老师: 2014年12月

目录 一、设计任务与要求 (3) 二、总体框图 (3) 三、选择器件 (3) 四、功能模块 (9) 五、总体设计电路图 (10) 六、心得体会 (12)

8位数码管动态显示电路设计 一、设计任务与要求 1. 设计个8位数码管动态显示电路,动态显示1、2、3、4、5、6、7、8。 2. 要求在某一时刻,仅有一个LED 数码管发光。 3. 该数码管发光一段时间后,下一个LED 发光,这样8只数码管循环发光。 4. 当循环扫描速度足够快时,由于视觉暂留的原因,就会感觉8只数码管是在持续发光。 5、研究循环地址码发生器的时钟频率和显示闪烁的关系。 二、总体框图 设计的总体框图如图2-1所示。 图2-1总体框图 三、选择器件 1、数码管 数码管是一种由发光二极管组成的断码型显示器件,如图1所示。 U13 DCD_HEX 图1 数码管 数码管里有八个小LED 发光二极管,通过控制不同的LED 的亮灭来显示出 不同的字形。数码管又分为共阴极和共阳极两种类型,其实共阴极就是将八个 74LS161计数器 74LS138译码 器 数码管

LED的阴极连在一起,让其接地,这样给任何一个LED的另一端高电平,它便能点亮。而共阳极就是将八个LED的阳极连在一起。 2、非门 非门又称为反相器,是实现逻辑非运算的逻辑电路。非门有输入和输出两个端,电路符号如图2所示,其输出端的圆圈代表反相的意思,当其输入端为高电平时输出端为低电平,当其输入端为低电平时输出端为高电平。也就是说,输入端和输出端的电平状态总是反相的。其真值表如表1所示。 图2 非门 表1 真值表 输入输出 A Y 0 1 1 0 3、5V电源 5V VCC电源如图3所示。 图3 5V电源

相关主题
文本预览
相关文档 最新文档