求TM1628驱动10位共阳数码管的例程
求个天微数码管驱动芯片的驱动程序,芯片TM1628,驱动10位共阳数码管的。要直接能驱动10位的,有做过的朋友帮个忙。
现在我已经在网上找到了驱动程序,改了后可以驱动10位共阳的,但是跟其他程序一起放到大循环其他模块的功能就实现不了,屏蔽了显示,其他功能就能实现。
现在想看看你们怎么做的,参考参考下。 uchar Read_TM1668(void) { uchar i,byte = 0; for(i = 0; i < 8; i++) { byte >>= 1; CLR_TM1668_CLK; TM1668_DELAY; TM1668_DELAY; if(GET_TM1668_DIO != 0) byte |= 0x80; SET_TM1668_CLK; TM1668_DELAY; } return byte; }void Write_TM1668(uchar byte) { uchar i; for(i = 0; i < 8; i++) { CLR_TM1668_CLK; TM1668_DELAY; if((byte & BIT0) != 0) SET_TM1668_DIO; else CLR_TM1668_DIO; TM1668_DELAY; SET_TM1668_CLK; byte >>= 1; TM1668_DELAY; } } //set display mode CLR_TM1668_STB; Write_TM1668(0x03); SET_TM1668_STB; TM1668_DELAY; //set addr mode CLR_TM1668_STB; Write_TM1668(0x44); SET_TM1668_STB; TM1668_DELAY; //send display data j = 0xC0; for(i = 0; i < 5; i++) { CLR_TM1668_STB; Write_TM1668(j); Write_TM1668(u8_tmp); SET_TM1668_STB; TM1668_DELAY; j += 2; } //set bright CLR_TM1668_STB; Write_TM1668(0x8A); SET_TM1668_STB; 你自己都有驱动程序了,你是想让人家提供一个刚好能符合你其他功能的程序吗?只要在需要更新显示的时候再通信,不更新的时候,跟没有这个函数的程序是一样的,不需要放到大循环去每次循环执行 little_Monkey 发表于 2014-8-9 22:12
你自己都有驱动程序了,你是想让人家提供一个刚好能符合你其他功能的程序吗?只要在需要更新显示的时候再通 ...
也不是放到大循环里, 一开始我初始化显示后,定时器就不走,屏蔽了初始化显示,定时器就正常,反反复复测试了,因为这个显示函数影响到了,但是最终没看出是什么问题 billmcu 发表于 2014-8-9 22:01
//set display mode CLR_TM1668_STB; Write_TM1668(0x03); SET_TM1668_STB; TM1668_DELAY ...
{:sweat:} 好乱 jufr12315 发表于 2014-8-9 22:19
好乱
你说的根本就不是TM1628的问题
而是你程序架构的问题。你自己一点一点屏蔽分析一下就知道了呀。这样的问题来论坛问是不会有结果的。 STM32_Study 发表于 2014-8-9 23:25
你说的根本就不是TM1628的问题
而是你程序架构的问题。你自己一点一点屏蔽分析一下就知道了呀。这样的问 ...
{:mad:} 是啊,现在就想看看人家驱动程序的框架怎么写的 jufr12315 发表于 2014-8-9 23:45
是啊,现在就想看看人家驱动程序的框架怎么写的
这个很简单啊
void TM1628_Dirver(void)
{
if(TM1628_Update)
{
TM1628_Update = 0;
//update
}
}
就这样就OK了。 STM32_Study 发表于 2014-8-9 23:48
这个很简单啊
void TM1628_Dirver(void)
图中显示函数就在主循环前面,我只是测试下能不能显示。
不屏蔽可以显示,但是主循环里面的程序实现的功能就实现不了。
屏蔽了就可以实现。 你有看我发的帖子吗?
你的TM1628_Diaplay函数里面,有没有做这样的判断?
如果没有,那加上吧。
如果有,那就可能是溢出跑飞了。检查数组指针的调用吧。
只能帮到这里了。祝你好运 STM32_Study 发表于 2014-8-10 00:11
你有看我发的帖子吗?
你的TM1628_Diaplay函数里面,有没有做这样的判断?
好的,谢谢。 同感,我使用TM1650也遇到这个问题! nsj21n 发表于 2014-8-10 09:19
同感,我使用TM1650也遇到这个问题!
{:sweat:} 问题还没解决么?我都搞一天了,没找出问题。 楼主上个TM1650的资料我看看
也好帮你~~~~~~~~~~~~~~~~~~~~~~~
上面是TM1628驱动芯片手册。
下面是阴码转阳码的程序,记得是在论坛某位网友贴出来的程序。
lxa0 发表于 2014-8-10 14:14
楼主上个TM1650的资料我看看
也好帮你~~~~~~~~~~~~~~~~~~~~~~~
资料已传在16楼,我是用来驱动10位共阳数码管 本帖最后由 lxa0 于 2014-8-11 00:27 编辑
大概看了下TM1628规格书.pdf
说是共阴时可以驱动7个数码管
共阳时可以驱动10个数码管
资料里边还有电路和代码
当然了,c代码我看不懂
不过,既然资料里有说可以驱动共阳10个
那你就仿照例程试验
应该不会有问题的
资料里边还强调了:
seg1~10引脚只能接led阳极
也就是说
你要驱动10个led数码管的话
用共阳的数码管最好了
里边还有详细的说明和代码
你得仔细的去琢磨啦 lxa0 发表于 2014-8-11 00:19
大概看了下TM1628规格书.pdf
说是共阴时可以驱动7个数码管
共阳时可以驱动10个数码管
{:smile:} 谢啦,还在看,驱动例程是驱动共阴的,得改,现在是改后可以驱动,就是把驱动显示加入主函数就出问题,不是显示出问题,而是其他功能实现不了。
好啦,还是谢谢你。我自己再找找。 楼主把你完整的程序贴出来吧,这样别人才能帮你找问题呀
本帖最后由 jufr12315 于 2014-8-11 09:27 编辑
上面是整个工程
下面的TM1628部分代码
#include <main.H>
#include <TM1628.H>
sbit Pin_TM1628_STB1 = P1^2;
sbit Pin_TM1628_CLK1 = P1^1;
sbit Pin_TM1628_DIO1 = P1^0;
sbit Pin_TM1628_STB2 = P2^7;
sbit Pin_TM1628_CLK2 = P2^6;
sbit Pin_TM1628_DIO2 = P2^5;
uchar code ucTabBrightness[]={0x80,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f};//显示亮度表
unsigned char code ucTabCode[]=
{
0x3F, // 0
0x06, // 1
0x5B, // 2
0x4F, // 3
0x66, // 4
0x6D, // 5
0x7D, // 6
0x07, // 7
0x7F, // 8
0x6F, // 9
// 0xFF,//全亮 0x10
0x00,//全灭 0x11
};
//====================================================================
//=== 功能变量定义 ===//
uchar xdata dis_buf1; //显示数据缓存区
uchar xdata dis_buf11; //显示数据缓存区
uchar xdata dis_date1; //段码数据缓存区
uchar xdata dis_date11; //段码数据缓存区
uchar xdata dis_buf2; //显示数据缓存区
uchar xdata dis_buf22; //显示数据缓存区
uchar xdata dis_date2; //段码数据缓存区
uchar xdata dis_date22; //段码数据缓存区
uchar xdata key_tm; //键值数据缓存区
//====================================================================
//=== TM16XX共阴码转共阳码函数 ===//
//=== buf为准备转换的数据数组地址 ===//
//=== date为转换后存储数组的数组地址 =//
void A_To_K(unsigned char *buf,unsigned char *date)
{
uchar i,j,tmp,index;
for(i=0;i<8;i++)
{
tmp=*(buf + i);
for(j=0;j<8;j++)
{
if(i<8)
index=j;
else
index=j+1;
if(tmp&(1<<j))
{
*(date+index) |= (1<<i);
}
else
{
*(date+index) &=(~(1<<i));
}
}
}
}
//====================================================================
//=== TM1668驱动函数 ===//
void WriteByte(uchar w_data,char flag) //写一字节数据
{
uchar i;
if(1 == flag)
{
Pin_TM1628_STB1 = 0;
for(i=8;i!=0;i--)
{
Pin_TM1628_CLK1 = 0;
if(w_data&0x01)
Pin_TM1628_DIO1 = 1;
else
Pin_TM1628_DIO1 = 0;
Pin_TM1628_CLK1 = 1;
w_data >>= 1;
}
}
else
{
Pin_TM1628_STB2 = 0;
for(i=8;i!=0;i--)
{
Pin_TM1628_CLK2 = 0;
if(w_data&0x01)
Pin_TM1628_DIO2 = 1;
else
Pin_TM1628_DIO2 = 0;
Pin_TM1628_CLK2 = 1;
w_data>>=1;
}
}
}
//== 数码管显示 flag :1->TM1628芯片1显示 2->TM1628芯片2显示
//== Brighttness :亮度调节 级别 0-8
void TM1628_Display(char flag,char Brightness) //写多字节数据
{
uchar i;
if(1 == flag)
{
Pin_TM1628_CLK1 = 1;
Pin_TM1628_DIO1 = 1;
Pin_TM1628_STB1 = 1;
WriteByte(0x03,1); //7位10段
Pin_TM1628_STB1 = 1;
WriteByte(0x44,1); //写数据
Pin_TM1628_STB1 = 1;
for(i=0;i<7;i++) //7个地址
{
WriteByte(0xc0+(i*2),1); //写地址
WriteByte(dis_date1,1); //写显示数据到显存
Pin_TM1628_STB1 = 1;
}
for(i=0;i<7;i++)
{
WriteByte(0xc0+(i*2)+1,1); //写地址
WriteByte(dis_date11,1); //写显示数据到显存
Pin_TM1628_STB1 = 1;
}
WriteByte(ucTabBrightness,1); //开显示,亮度为10/16
Pin_TM1628_STB1 = 1;
}
else
{
Pin_TM1628_CLK2 = 1;
Pin_TM1628_DIO2 = 1;
Pin_TM1628_STB2 = 1;
WriteByte(0x03,2); //7位10段
Pin_TM1628_STB2 = 1;
WriteByte(0x44,2); //写数据
Pin_TM1628_STB2 = 1;
for(i=0;i<7;i++) //7个地址
{
WriteByte(0xc0+(i*2),2); //写地址
WriteByte(dis_date2,2); //写显示数据到显存
Pin_TM1628_STB2 = 1;
}
for(i=0;i<7;i++)
{
WriteByte(0xc0+(i*2)+1,2); //写地址
WriteByte(dis_date22,2); //写显示数据到显存
Pin_TM1628_STB2 = 1;
}
WriteByte(ucTabBrightness,27); //开显示,亮度为10/16
Pin_TM1628_STB2 = 1;
}
}
void main()
{
char i;
uiCount = 0;
uiTempCountStart = uiCount;
uiTempCycles = 0;
uiTempCountEnd = 500;
Init();
KeyInit();
Write12887(0x0a,0x20); //开振荡器 第一次使用DS12C887和在仿真中 都必须打开
Write12887(0x0B,0x06); //允许更新、设置格式为二进制,时钟为24小时制、开启闹钟
Write12887(0x0B,0x86);
Write12887(SEC_ADDR,0);
Write12887(MIN_ADDR,30);
Write12887(HOUR_ADDR,1);
Write12887(WEEK_ADDR,5);
Write12887(DAY_ADDR,8);
Write12887(MON_ADDR,8);
Write12887(YEAR_ADDR,14);
Write12887(0x0B,0x06);
Year = Read12887(YEAR_ADDR);
Mon = Read12887(MON_ADDR);
Day = Read12887(DAY_ADDR);
Hour = Read12887(HOUR_ADDR);
Min = Read12887(MIN_ADDR);
Sec = Read12887(SEC_ADDR);
Week = Read12887(WEEK_ADDR);
DisCount();//转换存到数组
for(i=0;i<8;i++)
{
dis_buf1=ucTabCode;//清零
dis_buf2=ucTabCode;//清零
dis_buf11=ucTabCode;
dis_buf22=ucTabCode;
}
A_To_K(dis_buf1,dis_date1);//将共阴代码转换成共阳代码 芯片1的 SEG1-SEG88位数码管
A_To_K(dis_buf11,dis_date11);// 芯片1的 SEG9-SEG10 2位数码管
A_To_K(dis_buf2,dis_date2);//将共阴代码转换成共阳代码
A_To_K(dis_buf22,dis_date22);
TM1628_Display(1,1);//写显示数据到TM16**显存中
TM1628_Display(2,1);
//上面两个显示函数屏蔽,主循环时间读取是能正常工作的,因为时间读取中每次秒位变化,我就点亮led半秒,就是时钟的冒号闪烁
//不屏蔽的话,led就不会闪烁,要么是不会进入扫描读取里面,要么就是时间没变化。但是这两个显示函数看不出影响到哪里,有时屏蔽一个显示函数led能闪烁
while(1)
{
// 时间读取
if(uiCount >= uiReadCountStart)
uiReadCycles = uiCount - uiReadCountStart;
else
uiReadCycles = 0xffff - uiReadCountStart + uiCount;
if(uiReadCycles > 10) //10ms
{
Conversion();
SecBuf = Sec;
Sec = Read12887(SEC_ADDR);
if(SecBuf != Sec)
bSecFlag = 1;
Year = Read12887(YEAR_ADDR);
Mon = Read12887(MON_ADDR);
Day = Read12887(DAY_ADDR);
Hour = Read12887(HOUR_ADDR);
Min = Read12887(MIN_ADDR);
Sec = Read12887(SEC_ADDR);
Week = Read12887(WEEK_ADDR);
M_Year = Year;
M_Mon= Mon;
M_Day= Day;
uiReadCountStart = uiCount;
uiReadCycles = 0;
}
// 按键扫描
if(uiCount >= uiKeyCountStart)
uiKeyCycles = uiCount - uiKeyCountStart;
else
uiKeyCycles = 0xffff - uiKeyCountStart + uiCount;
if(uiKeyCycles > 10) //20ms
{
Key(ReadKey());
uiKeyCountStart = uiCount;
uiKeyCycles = 0;
}
// 温度读取
if(uiCount >= uiTempCountStart)
uiTempCycles = uiCount - uiTempCountStart;
else
uiTempCycles = 0xffff - uiTempCountStart + uiCount;
if(uiTempCycles > uiTempCountEnd) //20ms
{
if(bTempConverFlag)
{
bTempConverFlag = 0;
ConversionTemp();
uiTempCountStart = uiCount;
uiTempCountEnd = 10;//10 * 2 =20ms
uiTempCycles = 0;
}
else
{
bTempConverFlag = 1;//启动转换
Temp = GetTemp();
uiTempCountStart = uiCount;
uiTempCountEnd = 500;//500 * 2 = 1000ms
uiTempCycles = 0;
}
}
DisCount();
}
}
void T0_ISR(void) interrupt 1
{
TH0 = ucTh;
TL0 = ucTl;
uiCount++;
if(bSecFlag)
{
Pin_Led = 0;
if(++Count500Ms == 250)//亮500MS
{
Pin_Led = 1;
Count500Ms = 0;
bSecFlag = 0;
}
}
} jufr12315 发表于 2014-8-11 00:42
谢啦,还在看,驱动例程是驱动共阴的,得改,现在是改后可以驱动,就是把驱动显示加入主函数就 ...
你要把显示程序做为子程序去调用才行啊
那样你才可以去做别的 lmt50211 发表于 2014-8-11 08:24
楼主把你完整的程序贴出来吧,这样别人才能帮你找问题呀
我已传了程序 看程序倒没什么问题,你可以先这样,先把显示调通,然后把其它的整合起来
lmt50211 发表于 2014-8-12 08:41
看程序倒没什么问题,你可以先这样,先把显示调通,然后把其它的整合起来
...
是哦,我现在就是这样做的,单显示可以了。
整合起来一起,显示还是可以的,但其他功能就不行。屏蔽了显示,其他功能貌似正常。
TMXXX 系列的最好有共阴的,这样显示程序比较简单。刚开始用时出现同样的失误,解决办法如下:
1.先定义显示缓存有几位数码管就定义几个字节的数组。
2.定时器中断程序将数组内容传到TMXXXX芯片内显存,达到双缓存的目的。
3.写一个子程序更新每位数码管的单片机内数组的内容,当相于手机的横屏或竖屏模式。
4.菜单或基它程序调用3步子程序就行了。
liguangqang 发表于 2014-8-12 13:09
TMXXX 系列的最好有共阴的,这样显示程序比较简单。刚开始用时出现同样的失误,解决办法如下:
1.先定义显 ...
谢谢朋友。
你说的这个我有点不明白,能否再详细点呢?
现在我总结出来了,我用了另一款天微的芯片TM1640,驱动的是16位共阴数码管,也要同样的问题,
就是在初始化的时候一调用显示函数,定时器就完全不会计数了,主循环也貌似不会循环,像是卡死在什么地方。
你知道是啥原因吗? UINT8 DispBuf; //显示缓存
UINT8 KeyVal; //键值缓环保
UINT16 TempVal; //温度值
//显示更新
void TM1628_Display(void)
{
for(i=0;i<8;i++)TM1628_WriteByte(1,DispBuf);
for(i=8;i<16;i++) TM1628_WriteByte(2,DispBuf);
}
//获取键值
void TM1628_GetKeyVal(void)
{
for(i=0;i<4;i++)TM1628_ReadByte(1,KeyVal);
}
//写段数据
void TM1628_ WriteSeg(UINT8 Seg, UINT8 Val)
{
//根据不同的段Seg,写入DispBuf[]相应的位
}
void main(void)
{
//硬件初始化
HW_Init();
//初始化DS12887
DS12887_Init();
//初始化TM1628
TM1628_Init();
while(1)
{
//软件消息
if(KeyVal & 0x80)
{
//冒号闪
TM1628_ WriteSeg(冒号段,冒号位取反);
//读取日期,时间数据
Year = Read12887(YEAR_ADDR);
//写入相应段
TM1628_ WriteSeg(年段,Year);
}
//设置键
if(KeyVal & 0x80)
{
//设置处理
//用TM1628_WriteSeg()更新提示在设置状态
}
//+键
if(KeyVal & 0x80)
{
//+处理
//用TM1628_WriteSeg()更新提示在+状态
}
//-键
if(KeyVal & 0x80)
{
//-处理
//用TM1628_WriteSeg()更新提示在-状态
}
}
}
void T0_ISR(void) interrupt 1//定时10ms
{
//定义状态机
static UINT8 Status = 0;
//定时刷新频率100Hz
TM1628_Display();
//获取键值,系统消息
TM1628_GetKeyVal();
if(Status == 0)
{
//启动温度转换
DS18B20_ConversionTemp();
}
if(Status == 50)
{
//获取温度值
TempVal = DS18B20_GetTemp();
//软件触发消息,频率1Hz
KeyVal |= 0x80;
}
}
再不明白,就没办法了 {:smile:} 用过1630和1668,抠下他们pdf上的例程,就可以用了。{:shocked:} 1628我一直驱动共阴的数码管,从来未试过共阳的,你这7×10驱动,小数点就不能驱动了。 wkman 发表于 2014-8-13 11:12
用过1630和1668,抠下他们pdf上的例程,就可以用了。
{:lol:} 有例程的,只是例程是驱动共阴的,要驱动共阳的程序比较麻烦,虽然可以显示,但是影响到其他程序模块功能的实现。
所以我就买了共阴的数码管跟另一个型号的驱动芯片,结果还是跟前面一样,显示可以,但还是影响到其他功能,现在怀疑是电路问题,
电流不够,或者干扰什么的,程序像是卡死,跑飞,晚上改改电路,试试看。 ilikemcu 发表于 2014-8-13 11:31
1628我一直驱动共阴的数码管,从来未试过共阳的,你这7×10驱动,小数点就不能驱动了。 ...
对啊,小数点不用它。
驱动共阳好麻烦,所以重新买了共阴的数码管。 liguangqang 发表于 2014-8-13 10:08
UINT8 DispBuf; //显示缓存
UINT8 KeyVal; //键值缓环保
UINT16 TempVal; //温度值
{:lol:} 哇哇,谢谢你写这么多,知道你说的了。
这款驱动芯片,不需要定时显示的。
只要在需要改变显示时重新写数据就好了。 如用共阳的,就得在内存中将数据转90度,双缓存定时刷新占用资源少,应该是比较合适。
当然可以不用定时刷新可以驱动,但程序结构比较乱,不易维护。
用于人机交互,最好想清楚软件架构。不然非常麻烦。 liguangqang 发表于 2014-8-13 12:21
如用共阳的,就得在内存中将数据转90度,双缓存定时刷新占用资源少,应该是比较合适。
当然可以不用定时 ...
数据已经转换了,呵呵。
晚上回去试试,谢谢你的建议。 问题解决,在单片机电源脚加滤波电容就好,估计是电流不够 本帖最后由 mcu_mouse 于 2014-9-26 14:40 编辑
之前内容错误,,重新回帖。 mcu_mouse 发表于 2014-9-26 13:16
“【p07u了 子子孙孙子子孙孙子子孙孙子子孙孙子子孙孙子子孙孙子子孙孙子子孙孙子子孙孙子子孙孙 ...
{:lol:} 你想怎样 mcu_mouse 发表于 2014-9-26 13:16
“【p07u了 子子孙孙子子孙孙子子孙孙子子孙孙子子孙孙子子孙孙子子孙孙子子孙孙子子孙孙子子孙孙 ...
你想怎样 pigy0754 发表于 2014-9-26 13:26
你想怎样
{:funk:} 才发现,应该是我看帖子的时候有事去了,我崽按的,2岁多的小屁股,就喜欢在我电脑上按。。。。。{:sweat:} jufr12315 发表于 2014-9-26 14:21
你想怎样
电脑在家里没关,肯定是小屁股给我在上面乱按。。。。。{:sweat:} liguangqang 发表于 2014-8-13 10:08
UINT8 DispBuf; //显示缓存
UINT8 KeyVal; //键值缓环保
UINT16 TempVal; //温度值
MARK…… 近期要用这个芯片,学习一下,谢谢
页:
[1]