h2so4new0 发表于 2011-8-28 13:27:37

关于使用M16的PD5/6/7口与TM1638通信显示8位数码的程序疑问

TM1638通信显示8位数码模块 购买于 http://item.taobao.com/item.htm?id=9559804356 按键数码管模块LED显示模块(8位数码管+8个LED+8

个按键) 示范程序中有些疑问,恳请解答:
以下是 文件TM1638.H的内容
#ifndef        _TM1638_H
#define        _TM1638_H

#include        <avr/io.h>
#include        <util/delay.h>
#include        <avr/pgmspace.h>

#define        DATA_COMMAND        0X40
#define        DISP_COMMAND        0x80
#define        ADDR_COMMAND        0XC0

#define SET_BIT(PORT,BIT)        PORT|=(1<<BIT)
#define        CLR_BIT(PORT,BIT)        PORT&=~(1<<BIT)
#define        BIT_IN(DDR,BIT)                DDR&=~(1<<BIT)
#define        BIT_OUT(DDR,BIT)        DDR|=(1<<BIT)
#define        READ_BIT(PIN,BIT)        (PIN&(1<<BIT))

#define        DIO        PD7
#define        CLK        PD6
#define        STB        PD4

#define DIO_high                SET_BIT(PORTD,DIO)
#define DIO_low                        CLR_BIT(PORTD,DIO)
#define CLK_high                SET_BIT(PORTD,CLK)
#define CLK_low                        CLR_BIT(PORTD,CLK)
#define STB_high                SET_BIT(PORTD,STB)
#define STB_low                        CLR_BIT(PORTD,STB)

#define DIO_IN                BIT_IN(DDRD,DIO)        //输入状态
#define DIO_OUT                BIT_OUT(DDRD,DIO)        //输出状态
#define        DIO_READ        READ_BIT(PIND,DIO)        //读引脚电平

/*
#define DIO_IN        DDRD&=~(1<<PD7)                //输入状态
#define DIO_OUT        DDRD|=(1<<PD7)                //输出状态
#define        DIO_READ        PIND&(1<<PD7)        //读引脚电平

//引脚定义???????????????????????????是否与上面重复了,只不过这里的定义更直接了些,类似的还出现在DIO_IN _READ _OUT
#define DIO_high                PORTD|=(1<<PD7)
#define DIO_low                        PORTD&=~(1<<PD7)
#define CLK_high                PORTD|=(1<<PD6)
#define CLK_low                        PORTD&=~(1<<PD6)
#define STB_high                PORTD|=(1<<PD4)
#define STB_low                        PORTD&=~(1<<PD4)
*/
unsigned char tab[] PROGMEM={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
void TM1638_Write(unsigned char        DATA)                        //写数据函数
{
        unsigned char i;
        DIO_OUT;
        for(i=0;i<8;i++)
        {
                CLK_low;
                if(DATA&0X01)
                        DIO_high;
                else
                        DIO_low;
                DATA>>=1;
                CLK_high;
                _delay_us(1);
        }
}
unsigned char TM1638_Read(void)                                        //读数据函数
{
        unsigned char i;
        unsigned char temp=0;
        DIO_IN;
        _delay_us(1);
        for(i=0;i<8;i++)
        {
                temp>>=1;
                CLK_low;
                _delay_us(1);
                if(DIO_READ)    //????是否应该与 下面的CLK_high 交换位置 因为先置上升沿才能操作???
                        temp|=0x80;
                CLK_high;
        }
        return temp;
}
void Write_COM(unsigned char cmd)                //发送命令字
{
        STB_low;
        TM1638_Write(cmd);
        STB_high;
        _delay_us(1);
}
unsigned char Read_key(void)
{
        unsigned char c,i,key_value=0;
        STB_low;
        TM1638_Write(0x42);
        _delay_us(1);
        for(i=0;i<4;i++)
                c=TM1638_Read();
        STB_high;                                        //4个字节数据合成一个字节
        for(i=0;i<4;i++)
                key_value|=c<<i;    ///???这个没有很清楚重组后的KS1KS2KS3KS4...的顺序
        for(i=0;i<8;i++)
                if((0x01<<i)==key_value)
                        break;
        return i;
}
void Write_DATA(unsigned char add,unsigned char DATA)                //指定地址写入数据
{
        Write_COM(0x44);
        STB_low;
        TM1638_Write(0xc0|add);
        TM1638_Write(DATA);
        STB_high;
}
void Write_ALLDATA(unsigned char add,unsigned char *p,unsigned char cnt)
{
        unsigned char i;
        Write_COM(0x44);
        for(i=0;i<cnt;i++)
                {
                        Write_DATA(2*i,*(p+i));
                }
}
void Write_oneLED(unsigned char num,unsigned char flag)        //单独控制一个LED函数,num为需要控制的led序号,flag为0时熄灭,不为0时点亮
{
        if(flag)
                Write_DATA(2*num+1,1);
        else
                Write_DATA(2*num+1,0);
}
void Write_allLED(unsigned char LED_flag)                                        //控制全部LED函数,LED_flag表示各个LED状态
{
        unsigned char i;
        for(i=0;i<8;i++)
                {
                        if(LED_flag&(1<<i))
                                Write_DATA(2*i+1,3);
                        else
                                Write_DATA(2*i+1,0);
                }
}
void init_TM1638(void)
{
        unsigned char i;
        Write_COM(0x8b);//亮度
        Write_COM(0x40);
        STB_low;
        TM1638_Write(0xc0);
        for(i=0;i<16;i++)
                TM1638_Write(0x00);// 这里写的是0 还是全部消隐?
        STB_high;
}
#endif

这是按键数码管模块LED显示模块的附送例程ourdev_671959LHMKKB.rar(文件大小:658K) (原文件名:TM1638+按键数码管模块.rar)

little_Monkey 发表于 2011-8-28 22:21:58

这个产品是抄袭我们店里面的,这个函数也是直接使用我写的,我们现在的模块已经是双色led的了,并且已经由工厂贴片去做了
前面接口定义的地方没有重复,下面的定义是注释掉的,TM1638_Read函数里面的语句不能交换位置,注意是读函数,数据在clk的下降沿以后改变,在上升沿读入,至于重新组合读取到的4个字节的按键数据纯粹是为了简单方便,因为只有8个按键因此用一个8位的数据即可表示,这个地方需要结合硬件和手册里面的按键读取地址映射来思考,很简单的。。。

h2so4new0 发表于 2011-9-2 13:37:02

谢谢little Monkey
,支持正品。

贵店的淘宝地址在哪里?

YaphetS 发表于 2012-4-17 13:15:33

little_Monkey 发表于 2011-8-28 22:21 static/image/common/back.gif
这个产品是抄袭我们店里面的,这个函数也是直接使用我写的,我们现在的模块已经是双色led的了,并且已经由 ...

不知道 大侠 能不能共享下 程序。
或者提供下店铺地址

little_Monkey 发表于 2012-4-17 16:56:11

YaphetS 发表于 2012-4-17 13:15 static/image/common/back.gif
不知道 大侠 能不能共享下 程序。
或者提供下店铺地址

头文件,直接调用即可

#ifndef        _TM1638_H
#define        _TM1638_H

#include        <avr/io.h>
#include        <util/delay.h>
#include        <avr/pgmspace.h>

#define        DATA_COMMAND        0X40
#define        DISP_COMMAND        0x80
#define        ADDR_COMMAND        0XC0

#define SET_BIT(PORT,BIT)        PORT|=(1<<BIT)
#define        CLR_BIT(PORT,BIT)        PORT&=~(1<<BIT)
#define        BIT_IN(DDR,BIT)                DDR&=~(1<<BIT)
#define        BIT_OUT(DDR,BIT)        DDR|=(1<<BIT)
#define        READ_BIT(PIN,BIT)        (PIN&(1<<BIT))

#define        DIO        PD7
#define        CLK        PD6
#define        STB        PD4

#define DIO_high                SET_BIT(PORTD,DIO)
#define DIO_low                        CLR_BIT(PORTD,DIO)
#define CLK_high                SET_BIT(PORTD,CLK)
#define CLK_low                        CLR_BIT(PORTD,CLK)
#define STB_high                SET_BIT(PORTD,STB)
#define STB_low                        CLR_BIT(PORTD,STB)

#define DIO_IN                BIT_IN(DDRD,DIO)        //输入状态
#define DIO_OUT                BIT_OUT(DDRD,DIO)        //输出状态
#define        DIO_READ        READ_BIT(PIND,DIO)        //读引脚电平

/*
#define DIO_IN        DDRD&=~(1<<PD7)                //输入状态
#define DIO_OUT        DDRD|=(1<<PD7)                //输出状态
#define        DIO_READ        PIND&(1<<PD7)        //读引脚电平

//引脚定义
#define DIO_high                PORTD|=(1<<PD7)
#define DIO_low                        PORTD&=~(1<<PD7)
#define CLK_high                PORTD|=(1<<PD6)
#define CLK_low                        PORTD&=~(1<<PD6)
#define STB_high                PORTD|=(1<<PD4)
#define STB_low                        PORTD&=~(1<<PD4)
*/
unsigned char tab[] PROGMEM={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
void TM1638_Write(unsigned char        DATA)                        //写数据函数
{
        unsigned char i;
        DIO_OUT;
        for(i=0;i<8;i++)
        {
                CLK_low;
                if(DATA&0X01)
                        DIO_high;
                else
                        DIO_low;
                DATA>>=1;
                CLK_high;
                _delay_us(1);
        }
}
unsigned char TM1638_Read(void)                                        //读数据函数
{
        unsigned char i;
        unsigned char temp=0;
        DIO_IN;
        _delay_us(1);
        for(i=0;i<8;i++)
        {
                temp>>=1;
                CLK_low;
                _delay_us(1);
                if(DIO_READ)
                        temp|=0x80;
                CLK_high;
        }
        return temp;
}
void Write_COM(unsigned char cmd)                //发送命令字
{
        STB_low;
        TM1638_Write(cmd);
        STB_high;
        _delay_us(1);
}
unsigned char Read_key(void)
{
        unsigned char c,i,key_value=0;
        STB_low;
        TM1638_Write(0x42);
        _delay_us(1);
        for(i=0;i<4;i++)
                c=TM1638_Read();
        STB_high;                                        //4个字节数据合成一个字节
        for(i=0;i<4;i++)
                key_value|=c<<i;
        for(i=0;i<8;i++)
                if((0x01<<i)==key_value)
                        break;
        return i;
}
void Write_DATA(unsigned char add,unsigned char DATA)                //指定地址写入数据
{
        Write_COM(0x44);
        STB_low;
        TM1638_Write(0xc0|add);
        TM1638_Write(DATA);
        STB_high;
}
void Write_ALLDATA(unsigned char add,unsigned char *p,unsigned char cnt)
{
        unsigned char i;
        Write_COM(0x44);
        for(i=0;i<cnt;i++)
                {
                        Write_DATA(2*i,*(p+i));
                }
}
void Write_oneLED(unsigned char num,unsigned char flag)        //单独控制一个LED函数,并且不影响其他的led状态,num为需要控制的led序号,
{                                                                //flag为0时熄灭,为1时红灯亮,为2时绿灯亮,为3时亮橙色
        Write_DATA(2*num+1,flag&0x03);
}
void Write_allLED(unsigned char flag)                                        //控制全部LED函数,flag表示LED状态
{
        unsigned char i;
        for(i=0;i<8;i++)
                Write_DATA(2*i+1,flag&0x03);
}
void init_TM1638(void)
{
        unsigned char i;
        Write_COM(0x88);//亮度
        Write_COM(0x40);
        STB_low;
        TM1638_Write(0xc0);
        for(i=0;i<16;i++)
                TM1638_Write(0x00);
        STB_high;
}
#endif

wallacer 发表于 2013-3-1 15:40:44

little_Monkey 发表于 2012-4-17 16:56 static/image/common/back.gif
头文件,直接调用即可

#ifndef        _TM1638_H


谢谢楼主的共享精神!

lyny 发表于 2014-7-12 15:07:45

谢谢,刚好在用这个片子,不用自己调了
页: [1]
查看完整版本: 关于使用M16的PD5/6/7口与TM1638通信显示8位数码的程序疑问