/*显示程序,用STC15F2K60S2做显示芯片
// 硬件说明:P42 P43 P36 P37
0 0 电流表 0 0 无定义
0 1 计数器 0 1 1.9999V
1 0 显示器 1 0 199.99V
1 1 电压表 1 1 19.999V
//待显示数据由主机传来,定义5个字节的显示代码
//第一位是本机的确认代码,对本机而言,必须是“0”
//接下来三位是要显示的数据(高字节在前,低字节在后)
//第五个是要显示的小数点位置,可能值是0-4
//分别代表:0——不显示 1——十位,2——百位,3——千位 ,4——万位 ,个位后小数点固定不显示
99999 9999.9 999.99 99.999 9.9999
//接线:P07 P06 P05 P04 P03 P02 P01 P00
// e d h c g a f b
//0 0 0 1 0 1 0 0 0 0x28
//1 1 1 1 0 1 1 1 0 0xee
//2 0 0 1 1 0 0 1 0 0x32
//3 1 0 1 0 0 0 1 0 0xa2
//4 1 1 1 0 0 1 0 0 0xe4
//5 1 0 1 0 0 0 0 1 0xa1
//6 0 0 1 0 0 0 0 1 0x21
//7 1 1 1 0 1 0 1 0 0xea
//8 0 0 1 0 0 0 0 0 0x20
//9 1 0 1 0 0 0 0 0 0xa0
//A 0 1 1 0 0 0 0 0 0x60
//b 0 0 1 0 0 1 0 1 0x25
//C 0 0 1 1 1 0 0 1 0x39
//d 0 0 1 0 0 1 1 0 0x26
//E 0 0 1 1 0 0 0 1 0x31
//F 0 1 1 1 0 0 0 1 0x71
//H 1 1 1 1 1 1 1 1 0xff
//显示位接线 P15 P14 P13 P16 P12
// (高位)1 2 3 4 5(低位)
//p32(INT0)接时钟线,P33(INT1)接数据线*/
#include "STC15F2K60S2.H "
#include "UART.H" // 包含STC115F2K60S2单片机寄存器定义文件
#include <intrins.h>
#include "mcp3421.H"
#include "myfun.h"
#define Hidden 16
#define CmdDat 0 //命令字,不同显示器修改此数值即可
sbit Clock=P3^2; // 外部输入的时钟端
sbit Data=P3^3; // 外部输入的数据端
const unsigned int TimeOver=1000; //定义一个超时值(5字节通信)
unsigned char code DispCode[]={0x28,0xee,0x32,0xa2,0xe4,0xa1,0x21,0xea,0x20,0xa0,0x60,0x25,0x39,0x26,0x31,0x71,0xff};/*/显示代码*/
unsigned char code DispBit[]={0xdf,0xef,0xf7,0xbf,0xfb}; //位码表 (左边最高位)11011111(P1) 11101111(P1) 11110111(P1) 10111111(P1) 11111011(P1)(右边最低位)
unsigned long DispData=0; //用来显示的值
unsigned char DispBuf[5]={0,0,0,0,0}; //显示缓冲区 DispBuf[0]是左边最高位 DispBuf[4]是右边最低位
unsigned char RecDatCount; //接收的数据的计数器
unsigned char bdata RecDat; //接收到的数据
sbit RecDat0=RecDat^0; //定义接收数据的末位为RecDat0,这要求RecDat位于bdata空间中
bit renovate ; //更新数据的标志,为1,说明已接收到完整的4个字节,可以更新显示了
bit ReciveMark=1; // ?????????????
unsigned char DotCnt=1; //控制字,控制小数点的显示的。
unsigned char MaskSing=0; //控制字,确定究竟是否本机显示
bit StartOverCount; //一时有接收中断,则置位该位,如果收到40位,则清该位
unsigned int OverCount; //超时计数器,当有接收中断发生,就让这个计数器开始计数(每个T0中
//中断计数一次,如果这个计数器计到了200(即0.4秒)仍没有被清除,说明接收有误,由主程序清RecDatCount
unsigned long count=0; // 用于外部脉冲计数器中间变量,保存计数最高字节 FF FF FF = 16777215(16.7MHZ)
unsigned char temp0,temp1,temp2,temp3,temp4; // 最高位 temp0 ,最低位 temp4,5位最大显示99 999,只接收3字节,显示缓冲5字节。
// 中断程序用于完成5字节数据接收
void ReciveDate() interrupt 0 //外部中断0(int0)中断处理程序
{
ReciveMark=0;
if(StartOverCount==0) StartOverCount=1; //开启溢出计时器
RecDatCount++; //中断次数(0-40)
RecDat=RecDat<<1; //主机是先送高位,由左到右
if(Data)
RecDat0=1;
else
RecDat0=0;
if(RecDatCount==8) //接收完第一个数据
{
MaskSing=RecDat;
}
else if(RecDatCount==16) // 第2个数据,长整数最高字节
{
if(MaskSing==CmdDat) //与预设的命令码相同吗?
DispData=RecDat*65536;
}
else if(RecDatCount==24) // 第3个数据,长整数中间字节
{
if(MaskSing==CmdDat) //与预设的命令码相同吗?
DispData=DispData+RecDat*256;
}
else if(RecDatCount==32) // 第4个数据,长整数最低字节
{
if(MaskSing==CmdDat) //与预设的命令码相同吗?
DispData+=RecDat;
}
else if(RecDatCount==40) //否则就是第5个数据,即小数点显示位数
{
if(MaskSing==CmdDat) //多个显示器并联,可通过这个位进行区分
DotCnt=RecDat;
renovate=1; //要求刷新显示器
RecDatCount=0; //中断次数(0-40)
StartOverCount=0; //接收到40个字符,清标志
OverCount=0; //清超时计数器
RecDat=0;
}
}
/*
小数点显示控制分析,DotCnt是接收到主机提供的小数点位置信息,可能值是0-4
分别代表:0——不显示 1——十位,2——百位,3——千位,4——万位 ,个位后小数点固定不显示
显示条件: DotCnt == 4-Count
举例:DotCnt Count 显示否
0 0(最高位) NO
1 NO
2 NO
3 NO
1 0(最高位) NO
1 NO
2 NO
3 YES
2 0(最高位) NO
1 NO
2 YES
3 NO
3 0(最高位) NO
1 YES
2 NO
3 NO
4 0(最高位) YES
1 NO
2 NO
3 NO
*/
// 定时器程序用于完成5位数码管论流点亮
void Timer0() interrupt 1 //定时器T0的中断处理代码
{
unsigned char temp;
static unsigned char Count; //用于统计当前正显示哪一位(先显示左边最高位)
if(StartOverCount) //如果要求计数的标志是1
OverCount++; //计数器加1
// P1|=0x7c; //关断前次显示0111 1100
P1=0xff;
temp=DispBit[Count];
P1&=temp; //开启P1位控制
temp=DispBuf[Count]; //5位显示缓冲器BCD码
P0=DispCode[temp]; //查字形码表格(0-17)
if(Count<4) //显示小数点(最右端小数点不显示)
{
if(DotCnt==(4-Count))
{
P0&=0xDF; //点亮小数点h位置 1101 1111
}
}
Count++;
if(Count==5) Count=0;
TH0=(65536-3000)/256 ;
TL0=(65536-3000)%256 ;
}
void long_to_bcd(unsigned long dat)
{
unsigned char temp0,temp1,temp2,temp3,temp4; // 最高位 temp0 ,最低位 temp4,5位最大显示99 999,只接收3字节,显示缓冲5字节。
unsigned long temp;
temp=dat;
temp%=100000; // 如果收到的数超过10 0000则仅取小于10 0000的值
temp4 = temp % 10; // 获得个位
temp3 = temp / 10 % 10; // 获得十位
temp2 = temp / 100 % 10; // 获得百位
temp1 = temp / 1000 % 10; // 获得千位
temp0 = temp / 10000 % 10; // 获得万位
if((temp0==0)&&(DotCnt<4)) // 如果最高位等于0,而显示的小数点小于4位
DispBuf[0]=Hidden; // 那么最高位应该消隐
else
DispBuf[0]=temp0; // 否则将这个数送入最高位
if((temp0==0)&&(temp1==0)&&(DotCnt<3)) // 最高位、次高位同时为0,且小数点小于3位
DispBuf[1]=Hidden;
else
DispBuf[1]=temp1;
if((temp0==0)&&(temp1==0)&&(temp2==0)&&(DotCnt<2))
// 最高位、次高位、第三位均为0,且小数点小于2位时消隐
DispBuf[2]=Hidden;
else
DispBuf[2]=temp2;
if((temp0==0)&&(temp1==0)&&(temp2==0)&&(temp3==0)&&(DotCnt<1))
// 最高位、次高位、第三位、第四位均为0,且小数点小于1位(无)时消隐
DispBuf[3]=Hidden;
else
DispBuf[3]=temp3;
DispBuf[4]=temp4; // 最低位显示
}
// 主程序用于完成接收到的数据转BCD码放显示缓冲器
// 硬件说明:P42 P43 P36 P37
/*
0 0 无定义 0 0 无定义
0 1 计数器 0 1 1.9999V
1 0 显示器 1 0 199.99V
1 1 电压表 1 1 19.999V */
void main(void)
{
unsigned long temp;
TMOD=0X01;
TH0=(65536-3000)/256 ;
TL0=(65536-3000)%256 ;
TR0=1; // T0开始运行
ET0=1; // 定时器T0中断允许
PT0=0; // 将定时器置为低级中断
EA=1;
renovate=1; // 要求刷新显示器
Clock=1;
Data=1;
DispData=0X00; // 上电显示0.0000
DotCnt=4;