折腾xx1640驱动共阳数码管,显示只一次正常,刷新就乱码!
网上找的1640程序,多是驱动共阴数码管的,客户要共阳!找到个转换程序套上,可以正常显示0~9~abcd,但是,更新第二次显示,就是乱码,单独显示一次就正常???
折腾一天了,非常抓狂了???
源码如下 {:mad:} {:sweat:} {:dizzy:}
#include<reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SPK = P2^5;//BELL
sbit CLK = P1^6;//1640时钟线 1640接16个共阳8字管
sbit DIO = P1^5;//1640数据线
//命令说明
#define write_mode_z0x40//采用自动地址加一方式写显示缓存
#define write_mode_g0x44//地址固定模式
//#define read_mode 0x42//键盘扫描模式(1640无Key)
#define start_addr 0xc0//起始地址
#define disp_mode 0x8a//显示控制命令:开启+亮度(低3位)
#define close_disp 0x80//关显示bit-3
uchar code num[]={0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6, 0xEE,0x3E,0x9C,0x7A,0x9E,0x8E,};
//数码管码 0,1,2,3,4,5,6,7,8,9,A,b,C,d,E,F
uchar SEG={0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6, 0xEE,0x3E,0x9C,0x7A,0x9E,0x8E,};
//显示缓存:对应~共16个8字管
//******************************************************************
//延时1ms程序: IAP15W413AS_TSSOP28_IRC11.0592Mhz_1ms:(10,181)
//------------------------------------------------------------------
void Delay(uint count)//while(1){IO=~IO;Delay(1);}//Test!
{
uchar a,b;
while(count--!=0)
{ for(a=0;a<10;a++)
{
//WDT_CONTR=0x3c; //喂狗
for(b=0;b<155;b++);
} } }
//void delay_us(uint us){while(us--);}
void delay_us(uchar delay_time) //如果信号引脚接上电容 需增加延时
{
uchar i=delay_time;
while(i--)
{
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}
}
//********************************************************************
void init_1640(void)
{
CLK=0;delay_us(1);
DIO=1;delay_us(1);
CLK=1;delay_us(1);
DIO=0;delay_us(1);
}
//********************************************************************
void start_1640(void)
{
CLK=0;delay_us(1);
DIO=1;delay_us(1);
CLK=1;delay_us(1);
DIO=0;delay_us(1);
}
//********************************************************************
void stop_1640(void)
{
CLK=0;delay_us(1);
DIO=0;delay_us(1);
CLK=1;delay_us(1);
DIO=1;delay_us(1);
}
//********************************************************************
void send_1640(unsigned char in_data)
{
unsigned char i=0;
CLK = 0;
delay_us(1);
for( i=0;i<8;i++)
{
if(in_data&0x01)
{
DIO = 1;
delay_us(1);
}
else
{
DIO = 0;
delay_us(1);
}
CLK = 1;
delay_us(1);
in_data>>=1;
CLK = 0;
delay_us(1);
}
}
//********************************************************************
void disp_1640(void)
{
unsigned char i,j,k,ex_;
//---------------------------------
//共阴AH->BS共阳码(段/位)转换
//---------------------------------
for(i=0;i<16;i++)
{
k = i/8;
for(j=0;j<8;j++)
{
if(SEG & (0x80>>j) )
ex_ |= 1<<(i%8);
}
}
//---------------------------------
start_1640();
send_1640(write_mode_z);//地址自动增加1模式写显存
stop_1640();
start_1640();
send_1640(start_addr);//起始地址:从0xC0起
for(i=0;i<16;i++)
{
send_1640(ex_);//写数据
}
stop_1640();
start_1640();
send_1640(disp_mode); //控制命令:开显示+亮度
stop_1640();
}
//********************************************************************
//Main
//--------------------------------------------------------------------
void main(void)
{
unsigned char i=0,j=0;
SPK=1;Delay(200);//Test!
SPK=0;Delay(200);
SPK=1;Delay(200);
SPK=0;Delay(200);
init_1640();//初始化
//---------------------------------
while(1)
{
//---------------------------------
//以下代码独立可显示 FEdcbA~9~0
//---------------------------------
start_1640();
send_1640(close_disp);//关显示
stop_1640();
Delay(100);
for(i=0;i<16;i++)
SEG = num;//在16个8字管上显示:0~9~AbcdEF
disp_1640();
Delay(3000);
//---------------------------------
//以下代码独立可显示 FEdcbA~9~0 单独使用都显示正常,轮流显示,就是乱码了!!!
//---------------------------------
start_1640();
send_1640(close_disp);//关显示
stop_1640();
Delay(100);
for(i=0;i<16;i++)
SEG = num;//逆序显示:
disp_1640();
Delay(3000);
//---------------------------------
SPK=1;Delay(10);//Test!
SPK=0;Delay(10);
}
}
屏蔽 while里面的一段,就正常,,,但是数码管显示值,不可能固定,是要不断刷新的啊,,,一刷新要显示其它数据,就成下面状态了:而且,再刷回上次正确数据也不动,固定显示乱码界面:
本帖最后由 wkman 于 2019-10-30 20:59 编辑
屏蔽 while里面的一段,就正常,,,但是数码管显示值,不可能固定,是要不断刷新的啊,,,一刷新要显 ...
只要两个轮流显示打开,就固定成这个界面了,,,有使用经验的所说啥问题啊??? 客户还关心你用共阴还是共阳的数码管?这个是专门驱动共阴的,程序送数据符合习惯,驱动共阳转换起来本身就麻烦很多 void Start(void)
{
SCLK_high;
_delay_us(5);
DIN_high;
_delay_us(5);
DIN_low;
_delay_us(5);
// SCLK_low;
// _delay_us(5);
}
void Stop(void)
{
SCLK_high;
_delay_us(5);
DIN_low;
_delay_us(5);
DIN_high;
_delay_us(5);
}
void TM1640_Write(unsigned char DATA) //写数据函数
{
unsigned char i;
for(i=0;i<8;i++)
{
SCLK_low;
if(DATA&0X01)
DIN_high;
else
DIN_low;
_delay_us(5);
DATA>>=1;
_delay_us(5);
SCLK_high;
_delay_us(5);
}
}
void Write_COM(unsigned char cmd) //发送命令字
{
Start();
TM1640_Write(cmd);
Stop();
}
void Write_DATA(unsigned char add,unsigned char DATA) //指定地址写入数据
{
Write_COM(0x44);
Start();
TM1640_Write(0xc0|add);
TM1640_Write(DATA);
Stop();
}
这是我在用的TM1640的底层驱动 JY-MCU 发表于 2019-10-30 21:12
客户还关心你用共阴还是共阳的数码管?这个是专门驱动共阴的,程序送数据符合习惯,驱动共阳转换起来本身就 ...
{:sweat:} 是客户那边多用共阳,就指定用共阳8字管{:mad:} JY-MCU 发表于 2019-10-30 21:13
void Start(void)
{
SCLK_high;
转换为共阳,这这个函数里面实现了,且显示也正常,,,,我遇到的问题是,,,第二次修改更新全部16个数码管的显示值,,实现不了?成乱码了,,,这个我第一次遇到,以前用过很多tm的芯片,都没这次奇怪
//---------------------------------
//共阴AH->BS共阳码(段/位)转换
//---------------------------------
for(i=0;i<16;i++)
{
k = i/8;
for(j=0;j<8;j++)
{
if(buff_ & (0x80>>j) )
ex_ |= 1<<(i%8);
}
} void Write_DATA(unsigned char add,unsigned char DATA) //指定地址写入数据
{
Write_COM(0x44);
Start();
TM1640_Write(0xc0|add);
TM1640_Write(DATA);
Stop();
}
谢谢,,,试了下,这个固定地址方式,,,在我的板是没有任何显示??? 更新显示数据,就出现乱码,且再不可变了 ??? 1640/1680都用过,你好像没有应答信号! skype 发表于 2019-10-31 08:31
1640/1680都用过,你好像没有应答信号!
应答什么?{:funk:} void TM_I2C_Delay(void)
{
uint32_t i=5; /* 10us */
while(i)
{
i--;
}
}
/********************Start函数*************************/
void TM_I2CStart(void)
{
DIN_H;
CLK_H;
TM_I2C_Delay();
DIN_L;
TM_I2C_Delay();
CLK_L;
//TM_I2C_Delay();
}
/********************Stop函数*************************/
void TM_I2CStop(void)
{
CLK_L;
TM_I2C_Delay();
DIN_L;
TM_I2C_Delay();
CLK_H;
TM_I2C_Delay();
DIN_H;
TM_I2C_Delay();
}
/***************发送8bit数据,从低位开始**************/
void TM_Writebyte(uint8_t oneByte)
{
uint8_t i;
for(i=0;i<8;i++)
{
CLK_L;
TM_I2C_Delay();
if(oneByte&0x01)
DIN_H;
else
DIN_L;
oneByte=oneByte>>1;
CLK_H;
TM_I2C_Delay();
}
CLK_L;
//TM_I2C_Delay();
}
///
TM1640_GPIO_Configuration();
TM_I2CStart();
TM_Writebyte(0x40); //数据命令设置:普通模式,地址自动加一
TM_I2CStop();
TM_I2CStart();
TM_Writebyte(0xc0); //地址命令设置:初始地址00H
for(i=0;i<16;i++) //发送16位显示数据
{
TM_Writebyte(Led_data_buf);
}
TM_I2CStop();
//
void TM_FAN(uint8_t *p, uint8_t s)
{
const uint8_t fan_list[]={0x3,0x05,0x06};
TM_I2CStart();
TM_Writebyte(0xc0+5); //地址命令设置:初始地址00H
TM_Writebyte(*p &0xf8 + fan_list);
TM_I2CStop();
}
简单的驱动,没有出现过有乱码
wkman 发表于 2019-10-30 21:53
转换为共阳,这这个函数里面实现了,且显示也正常,,,,我遇到的问题是,,,第二次修改更新全部16个数 ...
位段操作,你只有 |= 置一,不见 &= 置零,要闹哪样?
之前统一清零了?
用 static 数组了?(只有初始化时清零) t3486784401 发表于 2019-11-1 01:36
位段操作,你只有 |= 置一,不见 &= 置零,要闹哪样?
之前统一清零了?
用 static 数组了?(只有初始化 ...
多谢回复{:handshake:}
在位段切换函数内,ex_数组在定义后,就是全0
unsigned char i,j,k,ex_;
然后只做 或操作,是1就赋值,是0还是保持0啊
ex_ |= 1<<(i%8);
,,,再刷新数据,就是一直乱码中{:sweat:} wkman 发表于 2019-11-1 09:55
多谢回复
在位段切换函数内,ex_数组在定义后,就是全0
没有初始化的局部数组!拿来的自信说全是零。
乱码后大多数笔段点亮就是这个毛病。
至少加上 ={0} 每次强制初始化啊。 t3486784401 发表于 2019-11-1 10:04
没有初始化的局部数组!拿来的自信说全是零。
乱码后大多数笔段点亮就是这个毛病。
{:sweat:}你是对的!!!! {:shy:} {:shy:} {:shy:}
这句改成这样就好了:T_T {:victory:}
unsigned char i,j,k,ex_={0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, }; 本帖最后由 wkman 于 2019-11-1 10:29 编辑
skype 发表于 2019-10-31 22:11
void TM_I2C_Delay(void)
{
uint32_t i=5; /* 10us */
多谢帮忙回复!{:handshake:}
TM_Writebyte(*p &0xf8 + fan_list); 这段代码也是“共阴管切换到共阳管”功能?
wkman 发表于 2019-11-1 10:22
多谢帮忙回复!
TM_Writebyte(*p &0xf8 + fan_list); 这段代码也是“共 ...
不是,是低三位要修改,而其他位不变。 能正常显示一次,说明共阴转共阳的部分没有问题。问题出现在刷新后,说明在刷新操作中有地方的数据混乱了{:lol:} rifjft 发表于 2019-11-1 15:34
能正常显示一次,说明共阴转共阳的部分没有问题。问题出现在刷新后,说明在刷新操作中有地方的数据混乱了{: ...
{:sweat:} 是啊非常低级的错误,,,,幸亏网友指出了,否则又要折腾去打共阴数码管的板了
页:
[1]