从头学玩单片机STC15F104W《五》点亮由FD650B驱动的电子屏(中九接收机屏)
编辑时间:2022-05-28 作者:金满斗 浏览量:2467 来源:原创

功    能: 点亮由FD650Bic驱动的电子屏,并实现按一下按键就数字加1,本来想时间周期里可以自动加1的,结果好像有冲突,以后再说    芯片型号STC15F104W

先找650b的厂家看资料,就看到了几个说明书。并没有想象中的源码,然后网上到处百度,找的的资料是偏面向对象的写法,看不懂,自己瞎撸吧。

显示屏板子就直接用的3代中九接收机的前面板,这里我们多。

最终效果。

中九的那个面板图也找了份。

话不多说,直接上源码吧。

先上hd650.h文件


#ifndef __FP__FD650__H
#define __FP__FD650__H

/*** type redefine ***/

typedef unsigned char MS_U8;
typedef unsigned short MS_U16;
typedef unsigned long MS_U32;
typedef int MS_S32;
typedef int MS_BOOL;


/****************************begin for FD650 define struct***************************** */
#define LEDMAPNUM 40

//key mapping
typedef struct
{
  MS_U8 keyMapData;
  MS_U8 keyMapLevel;

} MS_KEYMAP;

//led mapping
typedef struct _led_bitmap
{
  MS_U8 character;
  MS_U8 bitmap;
} led_bitmap;

//数码管显示常量
static const led_bitmap bcd_decode_tab[LEDMAPNUM] =
{	{'0', 0x3F}, {'1', 0x06}, {'2', 0x5B}, {'3', 0x4F},
    {'4', 0x66}, {'5', 0x6D}, {'6', 0x7D}, {'7', 0x07},
    {'8', 0x7F}, {'9', 0x6F}, {'a', 0x77}, {'A', 0x77},
    {'b', 0x7C}, {'B', 0x7C}, {'c', 0x58}, {'C', 0x39},
    {'d', 0x5E}, {'D', 0x5E}, {'e', 0x79}, {'E', 0x79},
    {'f', 0x71}, {'F', 0x71}, {'H', 0x76}, {'h', 0x74},
    {'o', 0x5C}, {'t', 0x78},
    {'l', 0x30}, {'L', 0x38}, {'N', 0x37},{'n', 0x37},
    {'p', 0x73},{'P', 0x73}, {'O', 0x3F}, {'u', 0x1C},
    {'U', 0x3E},{'S', 0x6D}, {'s', 0x6D},{'-', 0x40},
    {' ', 0x00}
};//BCD decode


/****************************end for FD650 define struct***************************** */

/* *************************************硬件相关*********************************************** */
#define HIGH 1
#define LOW  0

#define FRONTPNL_START_TIME_MS      3   //((1000 / 50) / LED_NUM)
#define FRONTPNL_PERIOD_TIME_MS     150
#define FP_LED_MAX_NUM                 4
#define FrontPnl_MSECS_TICK         100 //100 msecs/tick
#define FrontPnl_TICKS_SEC          1    //10 ticks/sec
/* ********************************************************************************************* */
// 设置系统参数命令

#define FD650_BIT_ENABLE  0x01    // 开启/关闭位
#define FD650_BIT_SLEEP   0x04    // 睡眠控制位
#define FD650_BIT_7SEG    0x08    // 7段控制位
#define FD650_BIT_INTENS1 0x10    // 1级亮度
#define FD650_BIT_INTENS2 0x20    // 2级亮度
#define FD650_BIT_INTENS3 0x30    // 3级亮度
#define FD650_BIT_INTENS4 0x40    // 4级亮度
#define FD650_BIT_INTENS5 0x50    // 5级亮度
#define FD650_BIT_INTENS6 0x60    // 6级亮度
#define FD650_BIT_INTENS7 0x70    // 7级亮度
#define FD650_BIT_INTENS8 0x00    // 8级亮度

#define FD650_SYSOFF  0x0400      // 关闭显示、关闭键盘
#define FD650_SYSON ( FD650_SYSOFF | FD650_BIT_ENABLE ) // 开启显示、键盘
#define FD650_SLEEPOFF  FD650_SYSOFF  // 关闭睡眠
#define FD650_SLEEPON ( FD650_SYSOFF | FD650_BIT_SLEEP )  // 开启睡眠
#define FD650_7SEG_ON ( FD650_SYSON | FD650_BIT_7SEG )  // 开启七段模式
#define FD650_8SEG_ON ( FD650_SYSON | 0x00 )  // 开启八段模式
#define FD650_SYSON_1 ( FD650_SYSON | FD650_BIT_INTENS1 ) // 开启显示、键盘、1级亮度
#define FD650_SYSON_4 ( FD650_SYSON | FD650_BIT_INTENS4 ) // 开启显示、键盘、4级亮度
#define FD650_SYSON_8 ( FD650_SYSON | FD650_BIT_INTENS8 ) // 开启显示、键盘、8级亮度


// 加载字数据命令
#define FD650_DIG0    0x1400      // 数码管位0显示,需另加8位数据
#define FD650_DIG1    0x1500      // 数码管位1显示,需另加8位数据
#define FD650_DIG2    0x1600      // 数码管位2显示,需另加8位数据
#define FD650_DIG3    0x1700      // 数码管位3显示,需另加8位数据
#define FD650_DOT     0x0080      // 数码管小数点显示
// 读取按键代码命令
#define FD650_GET_KEY 0x0700          // 获取按键,返回按键代码
      
#endif


然后上主程序文件


/********************************************************************
日    期:2022/05/28
功    能: 点亮由FD650Bic驱动的电子屏,并实现按一下按键就数字加1,本来想时间周期里可以自动加1的,结果好像有冲突再说    芯片型号STC15F104W	  
编    写:劲松电脑通讯	 www.jvbaopeng.com
*/
#include <stc15.h>
#include <fd650.h>
#define uchar unsigned char 
#define FOSC  18432000L 
//定义主时钟
#define TIMS (65536-FOSC/1000)    //1T模式,18.432MHz晶振
#define uint unsigned int  //宏定义无符号整型,16位的unsigned int允许的取值范围是0~65535。

sbit FD650_SCL = P3^4;    //屏驱动口
sbit FD650_SDA = P3^5;                     
sbit LED1=P3^3;        //灯
sbit key1=P3^2;	 //定义单片机P3口的第2位 (即P3.2)//为输入	   这里是7脚,就是按键

 //	微秒级延时
 void DELAY(uchar i){
	while(i--);
}

 //显示屏开始信号:保持 CLK 为“1”电平,DAT 从“1”跳“0”,认为是开始信号
static  void MDrv_FD650_Start( void ){
	FD650_SDA = 1;
	FD650_SCL = 1;
	DELAY(5);
	FD650_SDA = 0;
	DELAY(5);
	FD650_SCL = 0;
}

//显示屏结束信号:保持 CLK 为“1”电平,DAT 从“0”跳“1”,认为是结束信号
static  void MDrv_FD650_Stop( void ){
	FD650_SDA = 0;
	FD650_SCL = 1;
	DELAY(5);
	FD650_SDA = 1;
}

//写一个数据
static void MDrv_FD650_WrByte( MS_U8 dat )
{
    MS_U8 i; 
    for( i = 0; i != 8; i++ )   //数据循环8次,每一位判断数据是1还是0
    {
        if( dat & 0x80 ){	  //如dat为10010001,& 0x80,与10000000,结果为10000000,大于0,条件为真
            FD650_SDA = 1;     //所以只跟最前面的一位有关,首位为1结果为1,符合则让DTA输出1
        }else{
            FD650_SDA = 0;
        }
        DELAY(5);
        FD650_SCL = 1;     //一个时钟脉冲传输一位数据//CLK为高电平时数据必须保持不变
        dat <<= 1;
        DELAY(5);
        FD650_SCL = 0;      //直到CLK为低电平,一位数据传输结束
    }
    FD650_SDA = 1;     //写入,CLK从0跳到1,再从1跳到0	//写入650的内存
    DELAY(5);
    FD650_SCL = 1;
    DELAY(5);
    FD650_SCL = 0;
}

//写命令
static void MDrv_FD650_Write( MS_U16 cmd ) //write cmd
{
    MDrv_FD650_Start();
    MDrv_FD650_WrByte(((MS_U8)(cmd>>7)&0x3E)|0x40);
    MDrv_FD650_WrByte((MS_U8)cmd);
    DELAY(2);
    MDrv_FD650_Stop();
    return;
}
/*读取要显示内容的对应地址 */
static MS_U8 MDrv_Led_Get_Code(MS_U8 cTemp)
{
    MS_U8 i, bitmap = 0x00;
    for(i = 0; i < LEDMAPNUM; i++){
        if(bcd_decode_tab[i].character == cTemp){
		     bitmap = bcd_decode_tab[i].bitmap;
             break;
         }
    }
    return bitmap;
}

/*
*更新数据(文本数据地址,是否带中间两点)
*点亮数码管,注意,如果只有3位的话依次是点亮2,3,4管
*/
static void MDrv_FrontPnl_Update(MS_U8 *u8str, MS_BOOL Colon_flag)
{ 
    int i;
    MS_U8 LedBuffer[4];
    if(!u8str) return;
    for(i = 0; i < FP_LED_MAX_NUM; i++){	   // FP_LED_MAX_NUM 最大显示位数,在.h文件里定义了,这里是4
        LedBuffer[i] = MDrv_Led_Get_Code(u8str[i]);
    }
    MDrv_FD650_Write(FD650_SYSON_4);// 开启显示和键盘,4段显示方式
    //发显示数据
    MDrv_FD650_Write( FD650_DIG0 | LedBuffer[0] ); //点亮第一个数码管
    if(Colon_flag){
		MDrv_FD650_Write( FD650_DIG1 | LedBuffer[1] | FD650_DOT ); //点亮小数点
	}
	MDrv_FD650_Write( FD650_DIG1 | LedBuffer[1] );
	MDrv_FD650_Write( FD650_DIG2 | LedBuffer[2]); //点亮第三个数码管
	MDrv_FD650_Write( FD650_DIG3 | LedBuffer[3] | 0); //点亮第四个数码管		
}

//数字转文本(待转换数字)
static  MS_U8 *mystring(int Num){
	static  MS_U8 dat[4];
	dat[0]=Num%10000/1000+'0';
	dat[1]=Num%1000/100+'0';
	dat[2]=Num%100/10+'0';
	dat[3]=Num%10+'0';
	return dat;
}

//延迟
void  delayms(unsigned int ms)
{
 unsigned int i;
 do{
    i = FOSC/13000;
    while(--i);   
   }
 	while(--ms);
}
//========================================================================
// 函数: void tm0_isr  (void) interrupt TIMER0_VECTOR
// 描述:  timer0中断函数. 相当于于时间周期,大约1毫秒一个周期
// 参数: none.
// 返回: none.
//========================================================================
void tm0_isr (void) interrupt 1 using 1
{
   static uint  key_time = 0;   //局部计时
   static int mymun  = 0;
	 key_time++;
	 if(key_time>=(1000*2)){
	 	mymun++;
	 	LED1 = ~LED1;
		//MDrv_FrontPnl_Update(mystring(mymun),0);   //本来想让他按2秒走的,不晓得哪里冲突了,以后再说
	    key_time =0 ;
   }
   
}
//========================================================================
// 函数: TIME_INIT
// 描述: 定时器初始
// 参数: none.
// 返回: none.
//========================================================================
void TIME_INIT(){
	AUXR |=0x80;      //定时器0设置为1t模式
	TMOD = 0x00;         //设置定时器为模式0(16位自动装载)
	TL0 = TIMS;         //计时器初始化开始计时
	TH0 = TIMS >> 8 ;      //向右移动8位搞什么
	TR0 = 1;
	ET0 = 1;
	EA = 1;
}
///============================================== //

void main(void) 
{ 	  
 	int mm = 0;
	TIME_INIT();               
    MDrv_FrontPnl_Update((MS_U8*)" OFF",0);	   //来个初始显示,可以直接显示字符串的,传入文本指针
	while(1)
	{
		if(key1==0)
		{
			delayms(30);    //这里判断按键时长
			if(key1==0)
			{
				while(!key1);	   //这个必须加,表示判断按键是否松开,不然按键时灯闪烁
				mm++;
				MDrv_FrontPnl_Update(mystring(mm),0);    //显示按键加1
				
			}
		} 
	}
} 
最后源码也传到开源平台了,希望大家用的开心


来说两句吧