找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2620|回复: 8
打印 上一主题 下一主题
收起左侧

请教:单片机数码管位选问题和3秒后执行判断的问题

  [复制链接]
跳转到指定楼层
楼主
我做一个根据液体压力值进行电机相应的实验。
当压力小于8MPa时电机启动,启动3秒后压力没有上升就报警。
当压力大于12MPa时电机停止。
暂时用一个指示灯来模拟电机。用可调电阻模拟压力输入。
程序如下:

#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int

uchar code DSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
sbit CLK=P1^3;
sbit ST=P1^2;
sbit EOC=P1^1;
sbit OE=P1^0;
sbit LED=P1^7;    //指示灯

sbit L1=P2^0;
sbit L2=P2^1;
sbit L3=P2^2;
sbit L4=P2^3;

sbit LED2=P2^7;

void DelayMS(uint ms)
{
        uchar i;
        while(ms--)
                for(i=0;i<120;i++);
}
/******************显示采集的电压**********************************/
void Display_Result(uint d)
{
        L1=0;L2=1;L3=1;L4=1;   //P2=0xf7;     //1111 0111最右边的数码管显示
        P0=DSY_CODE[d%10];           
        DelayMS(5);
        
        L1=1;L2=0;L3=1;L4=1;    //P2=0xfb;     //左边第三个数码管  1111 1011
        P0=DSY_CODE[d%100/10];           
        DelayMS(5);
        
        L1=1;L2=1;L3=0;L4=1;     //P2=0xfd;     //左边第二个数码管  1111 1101
        P0=DSY_CODE[d%1000/100]|0x80;   //加小数点显示
        DelayMS(5);
        
        L1=1;L2=1;L3=1;L4=0;    //P2=0xfe;     //左边第一个数码管  1111 1110
        P0=DSY_CODE[d/1000];   
        DelayMS(5);

/*        if(d>=600 && d<=1000)
                { LED2=0;DelayMS(5);}
          else
                   LED2=1;  
*/
}

void main()
{
        uint temp;

        TMOD=0x02;
        TH0=0x14;
        TL0=0x00;
        IE=0x82;
        TR0=1;
        
        P1=0xbf; //通道选择  ABC=110表示选IN3为输入端 1011 1111 其中0对应的是C

        while(1)
        {
                ST=0;ST=1;ST=0;    //ADC启动
                while(EOC==0);       //空循环;转换结束信号,没结束时EOC一直为0,转换结束为高电平
               
                OE=1;                //输出使能
                temp=P3*1.0/255*500;     //ADC0808输出和输入之间的关系,P3是输出值,temp是输入值0-5V
                temp=3.4*temp;       //转换为压力显示,有可能是4位数
                Display_Result(temp);

                //如果压力小于8M,启动电机,启动后3秒,如果压力没有上升,就报警。如果压力大于12MPa,电机停止。
                if(temp<=800)
                { LED=0;   
                           //保存启动时的压力值
                           //保存启动时的时间
                }
                if(temp>=1200)
                        LED=1;

                OE=0;       //IF判断必须加在“使能”的中间,否则P3没有值了
        }
}

void Timer0_INT() interrupt 1
{
        CLK=~CLK;
}


现在的问题是:
1、指示灯接在P1.7可以正常实现效果。但是接在P2.7就不正常,只闪一下或者不停的闪烁。我想应该是在数码管位选时给的值导致的,如P2=0xfb  实际上把P1.7给置1(熄灭)了。
然后我把位选改成了只给定位选的4个端口,其它不赋值,但是P1.7还是不常亮,即使我在主程序开始给P2.7=0都不行,为什么?
2、启动3秒后,如果压力没有上升就报警。  怎么实现?是不是要用到定时器?(定时器我还不是很理解)
首先要保存电机启动时的压力和时间,然后计时3秒,再比较当前压力和保存的压力。但是这个计时不能再用delay来实现了吧,delay好像是整个进程都停止的吧?

如果P2剩下的端口我不能用,好像没有端口用来报警了?

位选问题.png (32.9 KB, 下载次数: 19)

位选问题.png
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:96682 发表于 2019-3-14 11:04 | 只看该作者
程序上 P2 端口设置与 LED2 有冲突,位显用 4 个就行
回复

使用道具 举报

板凳
ID:487930 发表于 2019-3-14 12:14 | 只看该作者
本帖最后由 wtm_lxy 于 2019-3-14 15:44 编辑
wc86110 发表于 2019-3-14 11:04
程序上 P2 端口设置与 LED2 有冲突,位显用 4 个就行

我把位选改成这样了:L1=0;L2=1;L3=1;L4=1;   //P2=0xf7;  
但是D2还是 不常亮,不知道为什么?
回复

使用道具 举报

地板
ID:234075 发表于 2019-3-14 16:23 | 只看该作者
1、你设置了两个LED,分别是P17和P27,冲突时自己造成的,和数码管的位选没有关系,因为你的位选是单独设置的L1\L2\L3\L4而不是直接对P2的操作,所以P2的其他几个IO口是可以正常使用的;
2、使用定时器中断是最好的选择,主函数中设置定时器中断(暂不启动)--循环检测到压力小于8MPa时电机启动,同时启动定时器开始计时--计时达到3秒且压力没有上升,则报警并停止中断(累加计时变量清零)
。这样的程序最好自己先画一个流程图,然后按照流程图进行程序的设计。

评分

参与人数 1黑币 +50 收起 理由
admin + 50 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

5#
ID:213173 发表于 2019-3-14 17:12 | 只看该作者
/******************显示采集的电压**********************************/
//不影响P2高4位状态的写法
void Display_Result(uint d)
{
        static uint count=0;
        static uchar i=0;
        if(++count>=500)//不影响其他程序运行的计数延时
        {
                count=0;
                P0=0x00;//消隐
                switch(i)
                {
                        case 0: P2&=0xf0;P2|=0xf7;P0=DSY_CODE[d%10];i++; break;
                        case 1: P2&=0xf0;P2|=0xfb;P0=DSY_CODE[d%100/10];i++; break;
                        case 2: P2&=0xf0;P2|=0xfd;P0=DSY_CODE[d%1000/100]|0x80;i++; break;
                        case 3: P2&=0xf0;P2|=0xfe;P0=DSY_CODE[d/1000];i=0; break;
                }
        }
}
回复

使用道具 举报

6#
ID:487930 发表于 2019-3-15 08:23 | 只看该作者
zhb2004xp 发表于 2019-3-14 16:23
1、你设置了两个LED,分别是P17和P27,冲突时自己造成的,和数码管的位选没有关系,因为你的位选是单独设置 ...

1、不好意思,这个冲突应该是没有的了。我修改了单片机中的程序引用目录,忘记更新对应关系了,所以修改了程序实际上没有生效。
2、定时器我试试看,还需要更努力的学习。

非常感谢您的回复。
回复

使用道具 举报

7#
ID:487930 发表于 2019-3-15 08:47 | 只看该作者
wulin 发表于 2019-3-14 17:12
/******************显示采集的电压**********************************/
//不影响P2高4位状态的写法
voi ...

非常感谢您的回复。
意思大概看懂了。
每计数500(延时多少?)就显示一个数字
4个数字显示完后,再循环。

顺便请教一下:
P2&=0xf0;   //P2=P2&0xf0;   逻辑与,高4位不变,低4位清零
P2|=0xf7;    //P2=P2|0xf7;   逻辑或,相加,高4为置1,第4位为7
后面这句还是用逻辑与吧?保持高四位不变,只修改低4位的值
回复

使用道具 举报

8#
ID:213173 发表于 2019-3-15 09:48 | 只看该作者
wtm_lxy 发表于 2019-3-15 08:47
非常感谢您的回复。
意思大概看懂了。
每计数500(延时多少?)就显示一个数字

1.《每计数500(延时多少?)就显示一个数字 》由于显示程序被主程序调用,主循环周期基本固定,所以每计数500延时多少不确定,这只是看你的程序做的估计,实际调试时以数码管不闪烁为准。一般在500us~2ms之间为宜。
2.逻辑与:&&,逻辑或:||,按位与:&、按位或:|。
P2&=0xf0;   //P2=P2&0xf0;   xxxx 0000
P2|=0xf7;    //P2=P2|0xf7;   xxxx 0111
回复

使用道具 举报

9#
ID:491172 发表于 2019-3-15 10:28 | 只看该作者
从图上可以看出,你p2.7是高电平,你这样怎么能点亮二极管呢?应该是p2.7是低电平才对.
好好再想一想,重敲一下代码!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表