首页 > 编程知识 正文

TM1640 数码管驱动代码简化版,数码驱动管芯片1668

时间:2023-05-03 21:10:21 阅读:179236 作者:3225

/*TM1640的SRAM写入数据格式------b7b 60---010-----地址模式(1 Byte ) 10----显式存储器地址)1 Byte ) data 1~N 地址1数据100----显示控制----1byte (命令类型:b7b6-----地址模式: 0 1显示控制:1------显示存储器地址:1----显示define DATA_MODE_FIXED0x44 //固定地址#define DATA_MODE_TEST0x48 //寻址模式---------------自动地址1336001000000x40固定地址: 01001000正常模式: 01001000测试模式x48---- x48 define DIS_DIS0x80 //的显示控制----------- b7b6----- B3 B2 B1 B0 (脉冲宽度)显示开关:1000000--- -显示关0x80100000001----显示开0x88消光数160 x 8910010104/160 x8a 10010110/160 x8b 1010101011/160 x8c 100010112/60x8d 10011013/160 x8e 1001114/160 x8f-----------160 x8c 存储器地址--------B7B6----B3B2B1B0 )显示单元0xc 0110000 grid 10xc 111000001 grid 20xc 211000000000 grid 30xc 3110001 grid 40xc id 60xc 61001010 grid 70xc 710010111 gr id80 xc 810000 grid 90xc 910100101 grid 100 xca 10010101010 grid 110 x CB 1100101010 grid 120 xcc 1010101010 d 140 xce 101010 grid 150111 grid 16-------------------- d 140 xce 1010 grid 150111 grid 16=========================================================================================//----- din :显示端口----数据侧DisCLK:显示端口----时钟侧    // 显示缓存/*--------------------------------- 各显示单元描述…---------------------------------*/u8 code SegCode[]={    //0x3F, 0x06, 0x5B, 0x4F, 0x66,  //  0~ 4: 0 1 2 3 4    //0x6D, 0x7D, 0x07, 0x7F, 0x6F,  //  5~ 9: 5 6 7 8 9    //0x77, 0x7C, 0x39, 0x5E, 0x79,  // 10~14: A b C d E    //0x71, 0x76, 0x38, 0x50, 0x54,  // 15~19: F H L r n    //0x1C, 0x73, 0x5C, 0x40, 0x00   // 20~24: u P o - null(熄灭)};

端口驱动函数:

/**===================================================================== 驱动功能函数 SCLK: ──┐                   SCLK:  ┌──         └─                        ─┘  DIN: ─┐    //开始           DIN:   ┌─  //结束        └──                        ──┘          7   6   5   4   3   2   1   0 传输:   ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─       ──┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘        ┌───┐───┌───┐───┌───┐───┌───┐───┐ ┌       ─┘───└───┘───└───┘───└───┘───└───┘─┘            7   6   5   4   3   2   1   0=====================================================================**///开始-----------------------------void start(void){  //首次开始前(初始化期间)先触发1次结束, 以使SCLK=1, DIN=1  DisDIN = 0;      //DIN由H→L, 开始  DisCLK = 0;      //置SCLK为L, 为发送DIN位作准备}//发送数据-------------------------void Send_DisDat(u8 dx){  u8 i;  for(i=0; i<8; i++){          //开始时已置SCLK=0    DisDIN = (bit)(dx & 0x01); //发送位, 低位先传    DisCLK = 1;                //位发送结束-DIN信号保持    dx   >>= 1;    DisCLK = 0;                //置SCLK=0, 为发送下一位/结束准备  }  //DisDIN = 0;               //该条语句与结束函数中的首条重复, 故可省掉}//结束-----------------------------void stop(void){  DisDIN = 0;  DisCLK = 1;                  //置SCLK为H-结束准备  DisDIN = 1;                  //DIN由L→H, 结束, 为下一次开始准备}

注:以上三段函数省掉了不必要的语句,但须在初始化阶段完成端口电平的就绪状态(也即是结束数据传输后的状态)。

实际运行的数据信号波形(黄色为SCLK,青色为DIN):

提示:根据TM1640的规格书说明——CLK为高电平时,DIN高电平->低电平即为开始;CLK为高电平时,DIN低电平->高电平即为结束。换句话说就是,TM1640在下降沿捕捉开始信号,上升沿捕捉结束信号,且开始/结束信号的捕捉区间为CLK处于高电平时。 CLK处于低电平时为 数据信号的捕捉区间,且捕捉发生在CLK的上升沿。

为何要分为三段函数,而不是将它们合为一个函数?

因为在发送位数据的过程中有单字节和多字节数据 的区分,当然可以使用2层循环及使用指针传送单字节数据或数组地址来解决,比如下面的代码。但是,使用2层循环会涉及循环变量及必要的逻辑判断,且会消耗过多的执行时间,单单循环内末语句结束到退出循环——循环结束,就得10来个机器周期的时间,还不如使用函数调用(2~4个机器周期即完成)。

提示:对于底层操作代码,每一个多余的指令都会对直接影响上层操作代码的执行效率——若底层代码包含1条冗余代码,上层代码调用时可能会执行n多次该冗余代码。 简单来说,“一个很小的基数乘以一个很大的倍数”的问题对于底层 代码来说应需重视。

//数据紧凑发送---------------------void sendDisDat(u8 *p){ u8 i, j, dat, len; len = sizeof(p); //---------------------------开始 DisDIN = 0; //DIN由H→L, 开始 DisCLK = 0; //置SCLK为L, 为发送DIN位作准备 //-----------------------发送数据 for(i=0; i<len; i++){ //开始时已置SCLK=0 if(len==1){dat = p;}else{dat = p[i];} //单字节时指针值即为数据值,多字节时指针值为数组地址 for(j=0; j<8; j++){ DisDIN = (bit)(dat & 0x01); //发送位 DisCLK = 1; //位发送结束-DIN信号保持 dat >>= 1; DisCLK = 0; //置SCLK=0, 为发送下一位/结束准备 } } //---------------------------结束 DisDIN = 0; DisCLK = 1; //置SCLK为H-结束准备 DisDIN = 1; //DIN由H→L, 结束, 为下一次开始准备}

 

 数据据操作函数:

/**===================================================================== 函数名称: Update_DisDat 输    入: addr-显存地址, dx-8位地址数据 功能描述: 更新dx指定的地址的数据 说    明: =====================================================================**/void Update_DisDat(u8 addr, u8 dx){  start(); Send_DisDat(DATA_MODE_FIXED); stop(); //固定地址  start();    Send_DisDat(addr);                           //指定地址    Send_DisDat(DisBuf[dx]);                     //数据传输-1字符  stop();}/**===================================================================== 函数名称: UpdateAllDisDat 输    入: 无 功能描述: 更新所有显示数据 说    明: =====================================================================**/void UpdateAllDisDat(void){  u8 i;  //start(); Send_DisDat(DIS_DIS);        stop(); //显示关  start(); Send_DisDat(DATA_MODE_AUTO); stop(); //自动地址  start(); Send_DisDat(FIRST_ADDR);             //起始地址  for(i=0; i<15; i++){                          //数据传输开始-15字符    Send_DisDat(DisBuf[i]);  }  stop();                                       //数据传输结束  //start(); Send_DisDat(DIS_EN);         stop(); //显示开}/**===================================================================== 函数名称: DisBufFresh 输    入:  dat[]-计数器 功能描述: 错误时对应的编号闪烁 说    明: =====================================================================**/void DisBufFresh(u8 *dat){  //显示缓冲更新代码}

初始化函数:

/**===================================================================== 函数名称: Dis_Init() 输    入: 无 功能描述: 显示缓冲及驱动初始化 说    明: =====================================================================**/void DisBufInit(void){  u8 i;  stop();                               //触发1次结束, 以使SCLK=1, DIN=1  start(); Send_DisDat(DIS_EN); stop(); //显示开  for(i=0; i<16; i++){    DisBuf[i]  = SegCode[24];           //全部熄灭  }  UpdateAllDisDat();}

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。