专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
51单片机
P0^4口能发送一个字节吗?(一个字节八位)
2020-01-24 12:03
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
51单片机
10047
13
13
请大家看下图的电路,动态数码显示。
(原文件名:图像 1.jpg)
P0^4怎么能传一个字节呢?不是传一位吗?
这样的电路图有问题吗?
请解答
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
13条回答
grant-liao
2020-01-24 14:45
程序如下
#include "stc.h"
/***************************************************
* 大量宏定义,便于代码移植和阅读
***************************************************/
#define HIGH 1
#define LOW 0
#define LS164_DATA(x) {if((x))P0_4=1;else P0_4=0;}
#define LS164_CLK(x) {if((x))P0_5=1;else P0_5=0;}
#define SEG_PORT P0 //控制数码管字型码端口
unsigned char Timer0IRQEvent=0; //T/C0 中断事件
unsigned char Time1SecEvent=0; //定时1 秒事件
unsigned int TimeCount=0; //时间计数值
unsigned char SegCurPosition=0; //当前点亮的数码管
//为了验证共阳极的字型码是共阴极的反码,共阳极字型码为共阴极的反码
//共阳极字型码存储在代码区,用关键字"code"声明
code unsigned char SegCode[10]={~0x3F,~0x06,~0x5B,~0x4F,~0x66,~0x6D,~0x7D,
~0x07,~0x7F,~0x6F};
//片选数码管数组,存储在代码区,用关键字"code"声明
code unsigned char SegPosition[4]={0xf7,0xfb,0xfd,0xfe};
//数码管显示数据缓冲区
unsigned char SegBuf[4] ={0};
/****************************************
*函数名称:LS164Send
*输入:无
*输出:无
*功能:74LS164 发送单个字节
******************************************/
void LS164Send(unsigned char byte)
{
unsigned char j;
for(j=0;j<=7;j++)//对输入数据进行移位检测
{
if(byte&(1<<(7-j))) //检测字节当前位
{
LS164_DATA(HIGH); //串行数据输入引脚为高电平
}
else
{
LS164_DATA(LOW); //串行数据输入引脚为低电平
}
LS164_CLK(LOW); //同步时钟输入端以一个上升沿结束确定该位的值
LS164_CLK(HIGH);
}
}
/****************************************
*函数名称:SegRefreshDisplayBuf
*输入:无
*输出:无
*功能:数码管刷新显示缓存
******************************************/
void SegRefreshDisplayBuf(void)
{
SegBuf[0] =TimeCount%10; //个位
SegBuf[1] =TimeCount/10%10; //十位
SegBuf[2] =TimeCount/100%10; //百位
SegBuf[3] =TimeCount/1000%10; //千位
}
/****************************************
*函数名称:SegDisplay
*输入:无
*输出:无
*功能:数码管显示数据
******************************************/
void SegDisplay(void)
{
unsigned char t;
SEG_PORT = 0x0F; //熄灭所有数码管
t = SegCode[SegBuf[SegCurPosition]]; //确定当前的字型码
LS164Send(t);
SEG_PORT = SegPosition[SegCurPosition];//选中一个数码管来系显示
if(++SegCurPosition>=4) //下次要点亮的数码管
{
SegCurPosition=0;
}
}
/****************************************
*函数名称:TimerInit
*输入:无
*输出:无
*功能:T/C 初始化
******************************************/
void TimerInit(void)
{
TH0 = (65536-5000)/256;
TL0 = (65536-5000)%256; //定时5MS
TMOD = 0x01; //T/C0 模式1
}
/****************************************
*函数名称:Timer0Start
*输入:无
*输出:无
*功能: T/C0 启动
******************************************/
void Timer0Start(void)
{
TR0 = 1;
ET0 = 1;
}
/****************************************
*函数名称:PortInit
*输入:无
*输出:无
*功能:I/O 口初始化
******************************************/
void PortInit(void)
{
P0=P1=P2=P3=0xFF;
}
/****************************************
*函数名称:main
*输入:无
*输出:无
*功能:函数主体
******************************************/
void main(void)
{
PortInit();
TimerInit();
Timer0Start();
SegRefreshDisplayBuf();
EA=1;
while(1)
{
if(Timer0IRQEvent) //检测定时中断事件是否产生
{
Timer0IRQEvent=0;
if(Time1SecEvent) //检测1 秒事件是否产生
{
Time1SecEvent=0;
if(++TimeCount>=9999)//计数值自加
{
TimeCount=0;
}
SegRefreshDisplayBuf();//刷新缓冲区
}
SegDisplay(); //点亮选中的数码管
}
}
}
/****************************************
*函数名称:Timer0IRQ
*输入:无
*输出:无
*功能:T/C0 中断服务函数
******************************************/
void Timer0IRQ(void) interrupt 1
{
static unsigned int cnt=0;
TH0 = (65536-5000)/256;
TL0 = (65536-5000)%256; //重载初值
Timer0IRQEvent=1;
if(++cnt>=200)
{
cnt=0;
Time1SecEvent=1;
}
}5
5) 实验代码
LS164Send 函数与模拟串口章节的SendByte 函数类似,都是移位传输的,LS164Send 函数是高字
节优先(MSB),模拟串口章节的SendByte 函数是低字节优先的(LSB)。
与数码管显示相关的函数有2 个,分别是数码管刷新显示缓存函数SegRefreshDisplayBuf 和数码
管显示数据函数SegDisplay。SegRefreshDisplayBuf 函数主要刷新为下一次数据的千位、百位、十
位、个位,起到暂存数据的作用,即所谓的“缓冲区”。SegDisplay 函数将缓冲区数据显示,
SegSegDisplay 函数最重要的一个操作就是动态显示下一个数码管的值是要首先熄灭所有数码管即
SEG_PORT = 0x0F,然后进入下一步操作,否则数码管显示时会有拖影。
与T/C 相关的函数有2 个,分别是T/C 初始化函数TimerInit 和T/C0 使能函数Timer0Start。
在main 函数当中,首先正确配置好T/C,启动T/C0,然后EA=1 允许所有中断。有一点要注意的是,
一定在进入while(1)之前调用SegRefreshDisplayBuf 函数来刷新当前数码管的显示缓存,否则第一
次显示的数据并不是我们想要见到的值。在进入while(1)死循环之后,不断检测T/C 中断事件标志位、
T/C 一秒事件标志位、计数值是否大于9999 ,接着就做相对应的操作。当计数值变化时,需要通过
SegRefreshDisplayBuf 函数来刷新当前数码管的显示缓存,最后通过SegDisplay 函数来显示当前
数码管的数值。
加载中...
查看其它13个回答
一周热门
更多
>
相关问题
【东软载波ESF0654 PDS开发板活动】开箱
1 个回答
东软载波ESF0654 PDS开发板外部中断
1 个回答
东软载波ESF0654 PDS开发板高级控制定时器AD16C4T
1 个回答
用串口调试助手为什么只能在hex模式接收发送而在文本模式不行
9 个回答
触摸芯片SC02B/SC04B在地砖灯的设计方案
1 个回答
相关文章
51单片机与蓝牙模块连接
0个评论
51单片机的硬件结构
0个评论
基于51单片机的无线遥控器制作
0个评论
51单片机 AD转换
0个评论
51单片机数码管递增显示
0个评论
如何实现对单片机寄存器的访问
0个评论
基于51单片机的指纹密码锁
0个评论
×
关闭
采纳回答
向帮助了您的知道网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
51单片机
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
×
付费偷看金额在0.1-10元之间
确定
×
关闭
您已邀请
0
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
#include "stc.h"
/***************************************************
* 大量宏定义,便于代码移植和阅读
***************************************************/
#define HIGH 1
#define LOW 0
#define LS164_DATA(x) {if((x))P0_4=1;else P0_4=0;}
#define LS164_CLK(x) {if((x))P0_5=1;else P0_5=0;}
#define SEG_PORT P0 //控制数码管字型码端口
unsigned char Timer0IRQEvent=0; //T/C0 中断事件
unsigned char Time1SecEvent=0; //定时1 秒事件
unsigned int TimeCount=0; //时间计数值
unsigned char SegCurPosition=0; //当前点亮的数码管
//为了验证共阳极的字型码是共阴极的反码,共阳极字型码为共阴极的反码
//共阳极字型码存储在代码区,用关键字"code"声明
code unsigned char SegCode[10]={~0x3F,~0x06,~0x5B,~0x4F,~0x66,~0x6D,~0x7D,
~0x07,~0x7F,~0x6F};
//片选数码管数组,存储在代码区,用关键字"code"声明
code unsigned char SegPosition[4]={0xf7,0xfb,0xfd,0xfe};
//数码管显示数据缓冲区
unsigned char SegBuf[4] ={0};
/****************************************
*函数名称:LS164Send
*输入:无
*输出:无
*功能:74LS164 发送单个字节
******************************************/
void LS164Send(unsigned char byte)
{
unsigned char j;
for(j=0;j<=7;j++)//对输入数据进行移位检测
{
if(byte&(1<<(7-j))) //检测字节当前位
{
LS164_DATA(HIGH); //串行数据输入引脚为高电平
}
else
{
LS164_DATA(LOW); //串行数据输入引脚为低电平
}
LS164_CLK(LOW); //同步时钟输入端以一个上升沿结束确定该位的值
LS164_CLK(HIGH);
}
}
/****************************************
*函数名称:SegRefreshDisplayBuf
*输入:无
*输出:无
*功能:数码管刷新显示缓存
******************************************/
void SegRefreshDisplayBuf(void)
{
SegBuf[0] =TimeCount%10; //个位
SegBuf[1] =TimeCount/10%10; //十位
SegBuf[2] =TimeCount/100%10; //百位
SegBuf[3] =TimeCount/1000%10; //千位
}
/****************************************
*函数名称:SegDisplay
*输入:无
*输出:无
*功能:数码管显示数据
******************************************/
void SegDisplay(void)
{
unsigned char t;
SEG_PORT = 0x0F; //熄灭所有数码管
t = SegCode[SegBuf[SegCurPosition]]; //确定当前的字型码
LS164Send(t);
SEG_PORT = SegPosition[SegCurPosition];//选中一个数码管来系显示
if(++SegCurPosition>=4) //下次要点亮的数码管
{
SegCurPosition=0;
}
}
/****************************************
*函数名称:TimerInit
*输入:无
*输出:无
*功能:T/C 初始化
******************************************/
void TimerInit(void)
{
TH0 = (65536-5000)/256;
TL0 = (65536-5000)%256; //定时5MS
TMOD = 0x01; //T/C0 模式1
}
/****************************************
*函数名称:Timer0Start
*输入:无
*输出:无
*功能: T/C0 启动
******************************************/
void Timer0Start(void)
{
TR0 = 1;
ET0 = 1;
}
/****************************************
*函数名称:PortInit
*输入:无
*输出:无
*功能:I/O 口初始化
******************************************/
void PortInit(void)
{
P0=P1=P2=P3=0xFF;
}
/****************************************
*函数名称:main
*输入:无
*输出:无
*功能:函数主体
******************************************/
void main(void)
{
PortInit();
TimerInit();
Timer0Start();
SegRefreshDisplayBuf();
EA=1;
while(1)
{
if(Timer0IRQEvent) //检测定时中断事件是否产生
{
Timer0IRQEvent=0;
if(Time1SecEvent) //检测1 秒事件是否产生
{
Time1SecEvent=0;
if(++TimeCount>=9999)//计数值自加
{
TimeCount=0;
}
SegRefreshDisplayBuf();//刷新缓冲区
}
SegDisplay(); //点亮选中的数码管
}
}
}
/****************************************
*函数名称:Timer0IRQ
*输入:无
*输出:无
*功能:T/C0 中断服务函数
******************************************/
void Timer0IRQ(void) interrupt 1
{
static unsigned int cnt=0;
TH0 = (65536-5000)/256;
TL0 = (65536-5000)%256; //重载初值
Timer0IRQEvent=1;
if(++cnt>=200)
{
cnt=0;
Time1SecEvent=1;
}
}5
5) 实验代码
LS164Send 函数与模拟串口章节的SendByte 函数类似,都是移位传输的,LS164Send 函数是高字
节优先(MSB),模拟串口章节的SendByte 函数是低字节优先的(LSB)。
与数码管显示相关的函数有2 个,分别是数码管刷新显示缓存函数SegRefreshDisplayBuf 和数码
管显示数据函数SegDisplay。SegRefreshDisplayBuf 函数主要刷新为下一次数据的千位、百位、十
位、个位,起到暂存数据的作用,即所谓的“缓冲区”。SegDisplay 函数将缓冲区数据显示,
SegSegDisplay 函数最重要的一个操作就是动态显示下一个数码管的值是要首先熄灭所有数码管即
SEG_PORT = 0x0F,然后进入下一步操作,否则数码管显示时会有拖影。
与T/C 相关的函数有2 个,分别是T/C 初始化函数TimerInit 和T/C0 使能函数Timer0Start。
在main 函数当中,首先正确配置好T/C,启动T/C0,然后EA=1 允许所有中断。有一点要注意的是,
一定在进入while(1)之前调用SegRefreshDisplayBuf 函数来刷新当前数码管的显示缓存,否则第一
次显示的数据并不是我们想要见到的值。在进入while(1)死循环之后,不断检测T/C 中断事件标志位、
T/C 一秒事件标志位、计数值是否大于9999 ,接着就做相对应的操作。当计数值变化时,需要通过
SegRefreshDisplayBuf 函数来刷新当前数码管的显示缓存,最后通过SegDisplay 函数来显示当前
数码管的数值。
一周热门 更多>