数码之家

 找回密码
 立即注册
搜索
查看: 2107|回复: 23

[综合] 用任意两个IO口驱动带TM1650芯片的四位数码管模块从0到9999自动走字

[复制链接]
发表于 2023-12-28 09:46:47 来自手机浏览器 | 显示全部楼层 |阅读模式
本帖最后由 林华信 于 2023-12-28 18:50 编辑

如题,请看图示。
视频过大,无法上传
把视频上传到自己的微信里,再下载下来才会减少容量,才能上传成功。好了,现在有视频了。
信者就不用看视频了,要扣币币的,不信就看吧!
工作时用5v供电,1级LED亮度(辉度)最大消耗30mA电流。电流随数显不同在26至30mA内变化。0级辉度是最大亮度,耗电多,1级亮度耗电最小。

买个TM1650芯片才1毛钱,还包邮,太超值了。以后用只有8个脚的单片机驱动数码管就用1650来搭档了,配4位共阴数码管来用,哈

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

打赏

参与人数 1家元 +18 收起 理由
cushion + 18 原創內容

查看全部打赏

发表于 2023-12-28 09:49:29 | 显示全部楼层
感觉还是整个电路板好些.
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-28 09:53:17 来自手机浏览器 | 显示全部楼层
xushu 发表于 2023-12-28 09:49
感觉还是整个电路板好些.

我这是临时性试验
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-28 09:55:00 来自手机浏览器 | 显示全部楼层
xushu 发表于 2023-12-28 09:49
感觉还是整个电路板好些.

化了几个大洋,买来一个模块,想立即试一下模块是否正常,所以马马虎虎搞一个电路试一下
回复 支持 1 反对 0

使用道具 举报

发表于 2023-12-28 10:01:18 | 显示全部楼层
只能看到图片,不分享一下代码吗?
回复 支持 反对

使用道具 举报

发表于 2023-12-28 10:04:11 | 显示全部楼层
用tm驱动数码管还是很简单的,网上例子很多,时许要求也不那么严格
回复 支持 反对

使用道具 举报

发表于 2023-12-28 10:21:00 | 显示全部楼层
jlc免费打板吧
回复 支持 反对

使用道具 举报

发表于 2023-12-28 10:32:41 | 显示全部楼层
刚刚赶紧把这个月的两张券领了
回复 支持 反对

使用道具 举报

发表于 2023-12-28 11:00:46 | 显示全部楼层
看个视频还要扣币,b站都没这么狠
回复 支持 反对

使用道具 举报

发表于 2023-12-28 11:24:41 | 显示全部楼层
blueruby 发表于 2023-12-28 11:00
看个视频还要扣币,b站都没这么狠

就没打算看,你看了吗,哈哈哈
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-28 11:37:27 | 显示全部楼层
林华信 发表于 2023-12-28 09:55
化了几个大洋,买来一个模块,想立即试一下模块是否正常,所以马马虎虎搞一个电路试一下 ...

   //8脚单片机,型号为 STC15F104W  SOP8封装,或STC15F类的,时钟频率:11.0592MHz
     

             
   
       /*程序功能:TM1650驱动程序加红外遥控解码程序 。遥控解码后显示在数码管上(还没有上机实验,我改为0到9999自动走字,走到9999就定住)



         时钟频率:11.0592MHz



*/

#include<stc15.h>//

unsigned int st,a;//---------------------------------我加的

unsigned char q,b,s,g;//---------------------------我加的

sbit scl = P3^3; //TM1650时钟通讯IO

sbit sda = P3^2;//TM1650数据通讯IO

sbit ir= P3^4;//红外输入口

sbit led = P3^5;//测试用指示灯,在调试红外遥控时可用

unsigned char ir_time = 0; //红外信号的时间,这个寄存器是为了在解码0/1(数据)的时候,用来计低电平的时间

bit ir_d = 0;//红外信号的高低标志位,

bit ir_ok = 0;//解码OK

unsigned char shuwei = 0;//解码的长度

unsigned char shuwei1 = 0;//解码的长度

unsigned char buzhou = 0;//解码的步骤

unsigned char ir_dat = 0;//红外的8位数据

unsigned char num[]={0,0,0,0};//红外的4组8位的数据,就是用户码,用户码反码,数据码,数据码反码

code unsigned char shuma[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //子模0-9,A,B,C,D,E,F

unsigned char reg1 = 0; //通用寄存器1

unsigned char reg2 = 0; //通用寄存器2??这两个寄存器在转换成可显示的数据要用到

void delay(unsigned int time)

{

while(time--);

}

void tm1650_start(); //TM1650通讯的开始信号

void tm1650_end();//TM1650通讯的结束信号

void tm1650_ack();//TM1650通讯的应答信号

void write_1();//TM1650数据通讯 写1

void write_0();//TM1650数据通讯 写0

void write_byte(unsigned char tem);//写一个字节

void TM0_Isr() interrupt 1 //红外解码,定时器的时基是50us中断一次

{

INT_CLKO &= 0xef; //关闭外部中断

if(buzhou==0)//步骤0,判断9ms的低电平

{

if(!ir)

{

ir_time++;

if(ir_time>185)//低电平超时,每一次因为错误退出解码时,一点要清掉用到的那些寄存器!!!!!!这里一点要注意,下面的退出里面也是要清掉

{

ir_d = 0;

ir_time = 0;

buzhou = 0;
TR0 = 0;

INT_CLKO |= 0x10;

}

}

else

{

if((ir_time>175)&&(ir_time<185)) //低电平OK,是正确的9ms ,就跳到步骤1? ? (9mS除以50uS=180,所以这里的值就设为175和185之间,因为要考虑到一点的误差)

{

ir_time = 0;

  led ^= 1;   //     去屏蔽----------------------------------------------------------------------111111

buzhou = 1;

}

else//不是正确的9ms

{

buzhou = 0;

TR0 = 0;

INT_CLKO |= 0x10;

}

}

}

if(buzhou==1)//步骤1,判断4.5ms的高电平

{

if(ir)

{

ir_time++;

if(ir_time>95) //高电平超时

{

ir_d = 0;

ir_time = 0;

buzhou = 0;

TR0 = 0;

INT_CLKO |= 0x10;

}

}

else

{

if((ir_time>85)&&(ir_time<95))//4.5ms高电平OK,就跳到步骤2??这里还可以添加判断连码的程序,如果这里的时间是2mS 那就是连码

{

ir_time = 0;

led ^= 1;  //-------------------------------------22222

buzhou = 2;

ir_d = 0;

}

else//不OK

{

buzhou = 0;

TR0 = 0;

INT_CLKO |= 0x10;

}

}

}

if(buzhou==2) //步骤2开始解码数据

{

if(!ir_d)//如果低电平标志为0时,这里是用来判断低电平的时间

{

if(!ir) //如果红外端口为低

{

ir_time++; //计低电平的时间

if(ir_time>13) //低电平时间超时,就退出解码

{

ir_d = 0;

ir_time = 0;

buzhou = 0;

TR0 = 0;

INT_CLKO |= 0x10;

shuwei = 0;

shuwei1 = 0;

}

}

else//如果转为高电平了,

{

ir_d = 1; //低电平标志位置一,要去判断高电平的时间了

ir_time = 0;//时间清零

}

}

else//如果低电平标志位为1,就是进入判断IR高电平的时间了,这个高电平的时间就是判断数据是0还是1

{

if(ir) //如果IR为高

{

ir_time++;//计高电平的是按

if(ir_time>34)//超时了就退出解码

{

ir_d = 0;

ir_time = 0;

buzhou = 0;

TR0 = 0;

INT_CLKO |= 0x10;

shuwei = 0;

shuwei1 = 0;

}

}

else//如果IR为低了,就可以判断高电频的时间了

{

if(ir_time>16)//时间大于16*50us??就是数据1

ir_dat |= 0x80;

else//否则就是数据0

ir_dat &= 0x7f;

shuwei++;

if(shuwei==8) //8bit 组成1byte

{

num[shuwei1]=ir_dat;

shuwei = 0;

shuwei1++;//总共4byte

if(shuwei1==4)//4组数据接收完了就接收解码

{

if(num[2]==0x45)  //----------------------------

led = 0;  //----------------------------------

else   //-------------------------------------

led = 1;   //--------------------------------

ir_ok = 1; //解码成功标志位置一

buzhou = 0;

TR0 = 0;

INT_CLKO |= 0x10;

shuwei1 = 0;

}

}

ir_dat>>=1;

ir_time = 0;

ir_d = 0;

}

}

}

}

void INT2_Isr() interrupt 10//IR为低 就进入此中断,开启解码,解码中这个中断是关闭的,只有退出了解码,才会进入这个中断

{

if(!ir)

{

buzhou = 0;

ir_d = 0;

shuwei = 0;

shuwei1 = 0;

ir_time = 0;

TR0 = 1;

}

}


void main()

{

P3M0 = 0x00;

P3M1 = 0x00;

P3 = 0xff;

AUXR |= 0x80; //定时器时钟1T模式

TMOD = 0x00;//模式0

TL0 = 0xD7;//设置定时初值

TH0 = 0xFD; //定时器0设为50us中断一次

TR0 = 0;//启动定时器

ET0 = 1;//使能定时器中断

INT_CLKO |= 0x10;//(EX2 = 1)使能INT2中断

EA = 1;

while(1)

{

tm1650_start();  //给从机 (即是tm1650芯片) 一个开始信号

write_byte(0x48); //写一个字节8位,就是发数码显示模式到从机(即是tm1650芯片)0x48是不能改变的。

tm1650_ack();     //从机应答

write_byte(0x11); //0x11,(1级亮度,开显示,7段,不显示小数点)。这里的指令数据 详情参阅TM1650的datasheet
                  //0x19,(1级亮度,开显示,8段,显示小数点)  
tm1650_ack();  //从机应答

tm1650_end();  //结束

//上面的语句已经让tm1650芯片做好了准备工作---------------------------------------------------------------------------------------------------------------------

//a=9999; //a可以是0-9999的任意一个十进制数

//以下4个语句,把9999这个十进制数分拆//能正常显示9999,验证了,OK
q=a/1000;//求出千位上的数字
b=(a-q*1000)/100;//求出百位上的数字
s=(a-q*1000-b*100)/10;//求出十位上的数字
g=(a-q*1000-b*100-s*10);//求出个位上的数字


//下面就可以分别给各位的数码值让它显示了(先高位,再低位)。格式:开始----发位选的数据------------应答----发段选,即要在本位显示的数字------应答----结束
  //tm1650芯片DIG1管脚接的数码管    开始----发位选的数据(千位)----应答---发段选,即(千位)要在本位显示的数字-------应答----结束
                                //DIG2接的数码管    开始----发位选的数据(百位)----应答---发段选,即(百位)要在本位显示的数字-------应答----结束
                                //DIG3接的数码管    开始----发位选的数据(十位)----应答---发段选,即(十位)要在本位显示的数字-------应答----结束
                                //DIG4接的数码管    开始----发位选的数据(个位)----应答---发段选,即(个位)要在本位显示的数字-------应答----结束


tm1650_start();//开始信号

write_byte(0x68);//发送千位的位地址      位选

tm1650_ack();

write_byte(shuma[q]); //发送千位的数字       // write_byte(shuma[reg1]);//千位的数字   段选(可变量)

tm1650_ack();

tm1650_end();


tm1650_start();

write_byte(0x6a);//百位的位地址      位选

tm1650_ack();

write_byte(shuma);//发送百位的数字 // write_byte(0x71);//write_byte(shuma[reg2]);//百位数字  段选(可变量)

tm1650_ack();

tm1650_end();


tm1650_start();

write_byte(0x6c);//十位的位地址      位选---------------

tm1650_ack();

write_byte(shuma);//发送十位的数字 //write_byte(0x77);//2  十位 write_byte(0x5b);十位数字  段选 固定显示2------------------------------write_byte(0x77);对的

tm1650_ack();

tm1650_end();


tm1650_start();

write_byte(0x6e);//个位的位地址      位选----固定显示

tm1650_ack();

write_byte(shuma[g]);//发送个位的数字//write_byte(0x66);//个位数字  段选 固定显示4。write_byte(0x3f);//个位固定显示0,这里固定显示02,是因为我们解码的数据是第2组数据,也就是数据码(第0组数据是用户码,1是用户码反码,2是数据码,3是数据码反码)
                 //write_byte(0x06);//个位固定显示1,
//{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //子模0-9,A,B,C,D,E,F

//  0    1    2      3    4    5    6    7   8    9    A    B    C    D    E    F
tm1650_ack();

tm1650_end();


//------------------------------------------------------------------------------------------------------------------------------------------------
delay(65530);//让a动起来。OK,验证了。

if(a<9999)a=a+1;//a的量能变了,数码管很快从0显示到9999,十位数位的字每1秒加1.



if(ir_ok)

{

ir_ok = 0; //清掉解码标志位

reg1 = (num[2]&0x0f);//??数据低4位送显示? ?? ?? ?? ???把数据转为0-F//-----==

reg2 = (num[2]&0xf0);//数据的高四位送显示                     //----------            






reg2>>=4;

}

}

}

void tm1650_start()

{

sda = 1;

scl = 1;

delay(10);

sda = 0;

delay(5);

}

void tm1650_end()

{

sda = 0;

scl = 1;

delay(6);

sda = 1;

delay(2);

}

void tm1650_ack()

{

while(sda);

delay(5);

scl = 1;

delay(5);

scl = 0;

delay(5);

}

void write_1()

{

sda = 1;

scl = 0;

delay(5);

scl = 1;

delay(10);

scl = 0;

delay(5);

sda = 0;

}

void write_0()

{

sda = 0;

scl = 0;

delay(5);

scl = 1;

delay(10);

scl = 0;

}

void write_byte(unsigned char tem)

{

unsigned char i;

for(i=8;i>0;i--)

{

if(tem&0x80)

write_1();

else

write_0();

tem<<=1;

}

}

/* void exter0() interrupt 1  //定时器0的中断程序
{
  st++;
  if(st==4000)st=0;
  if(st==200)
  {a++;
  if(a>9999)a=0;
  
  
  }


回复 支持 反对

使用道具 举报

发表于 2023-12-28 11:38:54 | 显示全部楼层
有两个人花巨资看了视频
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-28 11:39:31 | 显示全部楼层
林华信 发表于 2023-12-28 11:37
//8脚单片机,型号为 STC15F104W  SOP8封装,或STC15F类的,时钟频率:11.0592MHz
     

上传的程序被打了横线,哎------
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-28 11:40:48 | 显示全部楼层
林华信 发表于 2023-12-28 11:39
上传的程序被打了横线,哎------

程序是我修改别人的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-28 11:46:05 来自手机浏览器 | 显示全部楼层
hongo 发表于 2023-12-28 11:38
有两个人花巨资看了视频

信者就不用看,不信的就去看哈
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-28 12:30:31 来自手机浏览器 | 显示全部楼层
林华信 发表于 2023-12-28 11:46
信者就不用看,不信的就去看哈

这个程序被打了横线,复制后也不能用,泪奔啊
回复 支持 反对

使用道具 举报

发表于 2023-12-28 13:45:45 | 显示全部楼层
林华信 发表于 2023-12-28 12:30
这个程序被打了横线,复制后也不能用,泪奔啊
  1. let a=new Date();
复制代码



如此、这般,就不一样了

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-28 14:06:30 来自手机浏览器 | 显示全部楼层
devcang 发表于 2023-12-28 13:45
如此、这般,就不一样了

你看看,下面不是我发的代码,是论坛的帖子标题,全都打上了横线。啥原因????不解呀

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复 支持 反对

使用道具 举报

发表于 2023-12-28 17:47:42 | 显示全部楼层
一般来说测试时的电路都是凑合,没有问题了才做正规电路,期待正式结果。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-28 18:52:50 来自手机浏览器 | 显示全部楼层
wqwq212 发表于 2023-12-28 17:47
一般来说测试时的电路都是凑合,没有问题了才做正规电路,期待正式结果。 ...

对的,经常都是这样玩的。
回复 支持 反对

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-5-2 05:10 , Processed in 0.280801 second(s), 12 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

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