找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机不在同一端口数码管如何显示?

[复制链接]
跳转到指定楼层
楼主
ID:1112147 发表于 2024-3-8 18:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
共阴极三位数码管的段选不在同一个端口,该怎么用51单片机让数码管显示
sbit sega  = P0^1;//数码管段选引脚sbit segb  = P3^0;
sbit segc  = P3^4;
sbit segd  = P0^2;
sbit sege  = P0^3;
sbit segf  = P0^0;
sbit segg  = P3^1;
sbit segdp = P1^7;
sbit dir1  = P1^0;//数码管位选引脚
sbit dir2  = P1^1;
sbit dir3  = P3^3;


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:883242 发表于 2024-3-8 22:48 | 只看该作者
那就一个一个的置1或者0好了,没有别的办法。
回复

使用道具 举报

板凳
ID:1109793 发表于 2024-3-9 07:30 | 只看该作者
把显示内容放到一个字节,做个子程序专门把对应的位传递到对应的脚上
回复

使用道具 举报

地板
ID:213173 发表于 2024-3-9 07:51 | 只看该作者
任意端口组合驱动数码管
  1. #include <reg51.H>

  2. sbit sega  = P0^1;//数码管段选引脚
  3. sbit segb  = P3^0;
  4. sbit segc  = P3^4;
  5. sbit segd  = P0^2;
  6. sbit sege  = P0^3;
  7. sbit segf  = P0^0;
  8. sbit segg  = P3^1;
  9. sbit segdp = P1^7;
  10. sbit dir1  = P1^0;//数码管位选引脚
  11. sbit dir2  = P1^1;
  12. sbit dir3  = P3^3;

  13. unsigned char data table[17]={
  14.         0x3f,0x06,0x5b,0x4f,
  15.         0x66,0x6d,0x7d,0x07,
  16.         0x7f,0x6f,0x77,0x7c,
  17.         0x39,0x5e,0x79,0x71,0x00};

  18. void LED_dula(unsigned char dat)
  19. {
  20.         sega=dat   &0x01;
  21.         segb=dat>>1&0x01;
  22.         segc=dat>>2&0x01;
  23.         segd=dat>>3&0x01;
  24.         sege=dat>>4&0x01;
  25.         segf=dat>>5&0x01;
  26.         segg=dat>>6&0x01;
  27.         segdp=dat>>7&0x01;
  28. }

  29. void LED_wela(unsigned char dat)
  30. {
  31.         dir1=dat   &0x01;
  32.         dir2=dat>>1&0x01;
  33.         dir3=dat>>2&0x01;
  34. //        dir4=dat>>3&0x01;
  35. }

  36. void Delay_ms(unsigned int t)
  37. {
  38.         unsigned int i,j;
  39.         for(i=t;i>0;i--)
  40.                 for(j=120;j>0;j--);
  41. }

  42. void main()
  43. {
  44.         unsigned int i,j,k;
  45.         while (1)
  46.         {
  47.                 LED_wela(0xff);                        //位消隐
  48.                 LED_dula(table[i]);                //传段码
  49.                 LED_wela(~(0x01<<i));        //传位码
  50.                 i=++i%3;                                                //位循环计数
  51.                 if(++j>=1000)                                //移动显示
  52.                 {
  53.                         j=0;
  54.                         table[16]=table[0];
  55.                         for(k=0;k<16;k++)
  56.                                 table[k]=table[k+1];
  57.                 }       
  58.                 Delay_ms(1);                        //控制主循环周期
  59.         }
  60. }
复制代码
回复

使用道具 举报

5#
ID:1112147 发表于 2024-3-9 09:54 | 只看该作者
oid display_num(unsigned char n)
{
        unsigned char temp;
        temp = Tab[n];
        sega = temp & (0x01<<0);
        segb = temp & (0x01<<1);
        segc = temp & (0x01<<2);
        segd = temp & (0x01<<3);
        sege = temp & (0x01<<4);
        segf = temp & (0x01<<5);
        segg = temp & (0x01<<6);
}
消影这样可以吗?单个能显示对,三位一起显示就错
void xiao_ying(void)
{
        sega = 0;
        segb = 0;
        segc = 0;
        segd = 0;
        sege = 0;
        segf = 0;
        segg = 0;
}
void display_vvalue(unsigned char adc_value)
{
        unsigned char ge,shi,bai;
        ge  = adc_value % 10 ;
  shi = adc_value % 100 / 10;
  bai = adc_value / 100 ;
       
       
        display_num(ge);//送段码 个位
        dir1 = 0;//送位码
        delay_ms(3);//延时
        xiao_ying();//消影
       
       
        display_num(shi);//送段码 十位
        dir2 = 0;//送位码
        delay_ms(1);//延时
        xiao_ying();//消影

       
        display_num(bai);//送段码 百位
        dir3 = 0;//送位码
        delay_ms(1);//延时
  xiao_ying(); //消影
}
回复

使用道具 举报

6#
ID:1112147 发表于 2024-3-9 10:57 | 只看该作者
wulin 发表于 2024-3-9 07:51
任意端口组合驱动数码管

if(++j>=1000)                                //移动显示
                {
                        j=0;
                        table[16]=table[0];
                        for(k=0;k<16;k++)
                                table[k]=table[k+1];
                }      
                Delay_ms(1);                        //控制主循环周期
        }
大佬其他的都能看懂,就这一段看不懂
回复

使用道具 举报

7#
ID:41656 发表于 2024-3-9 11:43 | 只看该作者
自己写个函数把你编码的数据的每个位对应到各个IO就好了,处理速度没问题的放心搞
回复

使用道具 举报

8#
ID:1109793 发表于 2024-3-9 13:42 | 只看该作者
lqzd 发表于 2024-3-9 10:57
if(++j>=1000)                                //移动显示
                {
                       ...

每次主循环把显示内容向左循环移动一个位置,总工的代码风格非常间接高效。
比如本次循环显示123,下次显示234,大概是这样的。
回复

使用道具 举报

9#
ID:1109793 发表于 2024-3-9 13:43 | 只看该作者
lqzd 发表于 2024-3-9 10:57
if(++j>=1000)                                //移动显示
                {
                       ...

不对,是每1000次循环移动一次
回复

使用道具 举报

10#
ID:213173 发表于 2024-3-9 17:34 | 只看该作者
lqzd 发表于 2024-3-9 10:57
if(++j>=1000)                                //移动显示
                {
                       ...

xiaobendan001的解释是正确的,此段代码目的就是把0~F按一定时间间隔循环显示。检验一下数码管字符有无差错。
回复

使用道具 举报

11#
ID:883242 发表于 2024-3-9 19:41 | 只看该作者
wulin 发表于 2024-3-9 07:51
任意端口组合驱动数码管

严重怀疑segd=dat>>3&0x01;这种写法执行效率极其低下,建议让编译器输出汇编代码检查一下。

写成segd=dat&(0x01<<3);应该更好一些,这种写法的移位是编译时进行的,单片机没有移位操作,segd根据等号右边的值是0或者非零来置0或1。

我没有c51只是个建议。
回复

使用道具 举报

12#
ID:883242 发表于 2024-3-9 20:25 | 只看该作者
wulin 发表于 2024-3-9 07:51
任意端口组合驱动数码管

我用了DOS下面Franklin C51 V3.2(就是Keil在美国销售代理的名字)测试了一下,果然如果我所料,你的代码执行效率非常差。生成出来的汇编代码对比如下:

  1. ; void LED_dula(unsigned char dat)

  2.         RSEG  ?PR?_LED_dula?1801
  3.         USING        0
  4. _LED_dula:
  5.         MOV          dat?00,R7
  6.                         ; SOURCE LINE # 32
  7. ; {
  8.                         ; SOURCE LINE # 33
  9. ;         sega=dat   &0x01;
  10.                         ; SOURCE LINE # 34
  11.         MOV          A,dat?00
  12.         RRC          A
  13.         MOV          sega,C
  14. ;         segb=dat>>1&0x01;
  15.                         ; SOURCE LINE # 35
  16.         MOV          A,dat?00
  17.         CLR          C
  18.         RRC          A
  19.         RRC          A
  20.         MOV          segb,C
  21. ;         segc=dat>>2&0x01;
  22.                         ; SOURCE LINE # 36
  23.         MOV          A,dat?00
  24.         RRC          A
  25.         RRC          A
  26.         ANL          A,#03FH
  27.         RRC          A
  28.         MOV          segc,C
  29. ;         segd=dat>>3&0x01;
  30.                         ; SOURCE LINE # 37
  31.         MOV          A,dat?00
  32.         RRC          A
  33.         RRC          A
  34.         RRC          A
  35.         ANL          A,#01FH
  36.         RRC          A
  37.         MOV          segd,C
  38. ;         sege=dat>>4&0x01;
  39.                         ; SOURCE LINE # 38
  40.         MOV          A,dat?00
  41.         SWAP         A
  42.         ANL          A,#0FH
  43.         RRC          A
  44.         MOV          sege,C
  45. ;         segf=dat>>5&0x01;
  46.                         ; SOURCE LINE # 39
  47.         MOV          A,dat?00
  48.         SWAP         A
  49.         RRC          A
  50.         ANL          A,#07H
  51.         RRC          A
  52.         MOV          segf,C
  53. ;         segg=dat>>6&0x01;
  54.                         ; SOURCE LINE # 40
  55.         MOV          A,dat?00
  56.         SWAP         A
  57.         RRC          A
  58.         RRC          A
  59.         ANL          A,#03H
  60.         RRC          A
  61.         MOV          segg,C
  62. ;         segdp=dat>>7&0x01;
  63.                         ; SOURCE LINE # 41
  64.         MOV          A,dat?00
  65.         SWAP         A
  66.         RRC          A
  67.         RRC          A
  68.         RRC          A
  69.         ANL          A,#01H
  70.         RRC          A
  71.         MOV          segdp,C
  72. ; }
  73.                         ; SOURCE LINE # 42
  74.         RET         
  75. ; END OF _LED_dula

  76. ; void LED_dula1(unsigned char dat)

  77.         RSEG  ?PR?_LED_dula1?1801
  78.         USING        0
  79. _LED_dula1:
  80.         MOV          dat?10,R7
  81.                         ; SOURCE LINE # 43
  82. ; {
  83.                         ; SOURCE LINE # 44
  84. ;         sega=dat   &0x01;
  85.                         ; SOURCE LINE # 45
  86.         MOV          A,dat?10
  87.         RRC          A
  88.         MOV          sega,C
  89. ;         segb=dat&0x01<<1;
  90.                         ; SOURCE LINE # 46
  91.         MOV          A,dat?10
  92.         MOV          C,ACC.1
  93.         MOV          segb,C
  94. ;         segc=dat&0x01<<2;
  95.                         ; SOURCE LINE # 47
  96.         MOV          C,ACC.2
  97.         MOV          segc,C
  98. ;         segd=dat&0x01<<3;
  99.                         ; SOURCE LINE # 48
  100.         MOV          C,ACC.3
  101.         MOV          segd,C
  102. ;         sege=dat&0x01<<4;
  103.                         ; SOURCE LINE # 49
  104.         MOV          C,ACC.4
  105.         MOV          sege,C
  106. ;         segf=dat&0x01<<5;
  107.                         ; SOURCE LINE # 50
  108.         MOV          C,ACC.5
  109.         MOV          segf,C
  110. ;         segg=dat&0x01<<6;
  111.                         ; SOURCE LINE # 51
  112.         MOV          C,ACC.6
  113.         MOV          segg,C
  114. ;         segdp=dat&0x01<<7;
  115.                         ; SOURCE LINE # 52
  116.         RLC          A
  117.         MOV          segdp,C
  118. ; }
  119.                         ; SOURCE LINE # 53
  120.         RET         
  121. ; END OF _LED_dula1
复制代码


还有更好的写法:
  1. unsigned char bdata tmp;
  2. sbit tmp0=tmp^0;
  3. sbit tmp1=tmp^1;
  4. sbit tmp2=tmp^2;
  5. sbit tmp3=tmp^3;
  6. sbit tmp4=tmp^4;
  7. sbit tmp5=tmp^5;
  8. sbit tmp6=tmp^6;
  9. sbit tmp7=tmp^7;

  10. void LED_dula2(unsigned char dat)
  11. {
  12.         tmp=dat;
  13.         sega=tmp0;
  14.         segb=tmp1;
  15.         segc=tmp2;
  16.         segd=tmp3;
  17.         sege=tmp4;
  18.         segf=tmp5;
  19.         segg=tmp6;
  20.         segdp=tmp7;
  21. }
复制代码


最终生成的汇编就更加简洁了:
  1. ; void LED_dula2(unsigned char dat)

  2.         RSEG  ?PR?_LED_dula2?1801
  3.         USING        0
  4. _LED_dula2:
  5.         MOV          dat?20,R7
  6.                         ; SOURCE LINE # 54
  7. ; {
  8.                         ; SOURCE LINE # 55
  9. ;         tmp=dat;
  10.                         ; SOURCE LINE # 56
  11.         MOV          tmp,dat?20
  12. ;         sega=tmp0;
  13.                         ; SOURCE LINE # 57
  14.         MOV          C,tmp0
  15.         MOV          sega,C
  16. ;         segb=tmp1;
  17.                         ; SOURCE LINE # 58
  18.         MOV          C,tmp1
  19.         MOV          segb,C
  20. ;         segc=tmp2;
  21.                         ; SOURCE LINE # 59
  22.         MOV          C,tmp2
  23.         MOV          segc,C
  24. ;         segd=tmp3;
  25.                         ; SOURCE LINE # 60
  26.         MOV          C,tmp3
  27.         MOV          segd,C
  28. ;         sege=tmp4;
  29.                         ; SOURCE LINE # 61
  30.         MOV          C,tmp4
  31.         MOV          sege,C
  32. ;         segf=tmp5;
  33.                         ; SOURCE LINE # 62
  34.         MOV          C,tmp5
  35.         MOV          segf,C
  36. ;         segg=tmp6;
  37.                         ; SOURCE LINE # 63
  38.         MOV          C,tmp6
  39.         MOV          segg,C
  40. ;         segdp=tmp7;
  41.                         ; SOURCE LINE # 64
  42.         MOV          C,tmp7
  43.         MOV          segdp,C
  44. ; }
  45.                         ; SOURCE LINE # 65
  46.         RET         
  47. ; END OF _LED_dula2
复制代码
回复

使用道具 举报

13#
ID:213173 发表于 2024-3-9 21:28 | 只看该作者
Hephaestus 发表于 2024-3-9 19:41
严重怀疑segd=dat>>3&0x01;这种写法执行效率极其低下,建议让编译器输出汇编代码检查一下。

写成segd= ...

对于初学者而言,易懂比效率更适宜。何况在相同环境原代码执行时间35us,改后的代码执行时间64us,效率不升反降。
回复

使用道具 举报

14#
ID:1034262 发表于 2024-3-9 22:40 | 只看该作者
51单片机有一个很大的好处:位操作。
回复

使用道具 举报

15#
ID:883242 发表于 2024-3-10 14:47 | 只看该作者
wulin 发表于 2024-3-9 21:28
对于初学者而言,易懂比效率更适宜。何况在相同环境原代码执行时间35us,改后的代码执行时间64us,效率不 ...

算了吧你,你的代码每行要产生超过5条指令,我改了以后只有2条。
回复

使用道具 举报

16#
ID:1109793 发表于 2024-3-10 15:58 | 只看该作者
两位总工各有千秋
回复

使用道具 举报

17#
ID:213173 发表于 2024-3-10 20:49 | 只看该作者
Hephaestus 发表于 2024-3-10 14:47
算了吧你,你的代码每行要产生超过5条指令,我改了以后只有2条。

你是对的,我弄反了。原代码执行时间64us,改后的代码执行时间35us.
回复

使用道具 举报

18#
ID:1109793 发表于 2024-3-11 07:50 | 只看该作者
unsigned char bdata tmp;
sbit tmp0=tmp^0;
sbit tmp1=tmp^1;
sbit tmp2=tmp^2;
sbit tmp3=tmp^3;
sbit tmp4=tmp^4;
sbit tmp5=tmp^5;
sbit tmp6=tmp^6;
sbit tmp7=tmp^7;

void LED_dula2(unsigned char dat)
{
        tmp=dat;
        sega=tmp0;
        segb=tmp1;
        segc=tmp2;
        segd=tmp3;
        sege=tmp4;
        segf=tmp5;
        segg=tmp6;
        segdp=tmp7;
}
sbit还可以这样用啊?涨姿势了这回
回复

使用道具 举报

19#
ID:1064915 发表于 2024-3-11 09:16 | 只看该作者
dula、wela,这是什么词的缩写
回复

使用道具 举报

20#
ID:1108581 发表于 2024-3-11 10:30 | 只看该作者
牛逼牛逼,看到大佬之间的对话精彩之极,感叹我等道友何时能达到这种级别
回复

使用道具 举报

21#
ID:883242 发表于 2024-3-11 13:27 | 只看该作者
xiaobendan001 发表于 2024-3-11 07:50
unsigned char bdata tmp;
sbit tmp0=tmp^0;
sbit tmp1=tmp^1;

关键在于bdata
回复

使用道具 举报

22#
ID:1112147 发表于 2024-3-12 09:27 | 只看该作者
xiaobendan001 发表于 2024-3-11 07:50
unsigned char bdata tmp;
sbit tmp0=tmp^0;
sbit tmp1=tmp^1;

你能看明白吗?能不能给我解释一下,怎么能这样写的。
unsigned char bdata tmp;
sbit tmp0=tmp^0;
sbit tmp1=tmp^1;
sbit tmp2=tmp^2;
sbit tmp3=tmp^3;
sbit tmp4=tmp^4;
sbit tmp5=tmp^5;
sbit tmp6=tmp^6;
sbit tmp7=tmp^7;

void LED_dula2(unsigned char dat)
{
        tmp=dat;
        sega=tmp0;
        segb=tmp1;
        segc=tmp2;
        segd=tmp3;
        sege=tmp4;
        segf=tmp5;
        segg=tmp6;
        segdp=tmp7;
}
回复

使用道具 举报

23#
ID:883242 发表于 2024-3-12 14:48 | 只看该作者
lqzd 发表于 2024-3-12 09:27
你能看明白吗?能不能给我解释一下,怎么能这样写的。
unsigned char bdata tmp;
sbit tmp0=tmp^0;

你查下8051的RAM地址20h~2fh有和与众不同之处就知道了。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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