本帖最后由 芯圣电子官方QQ 于 2023-7-24 14:23 编辑
收到芯圣的仿真器,玩了一个星期,比较容易上手。下面是我自己写的一个温度检测程序,用LED显示的,完全可应用到产品上。借鉴官方例子里的看门狗,ADC,LED应用。现在正在研究驱动LCD液晶显示,过几天,写完程序,再跟大家分享。 #include "HC89F003.h"
/*********************************************************************************/
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
/***********************RAM太小,常量请放ROM中,加code.*放内部RAM加data*放外部RAM加xdata*不加默认放xdata********************/
/***********************LED段码表***P2.1-A,P2.2-E,P2.3-D,P2.4-C,P2.5-G,P2.6-DP,P0.6-F,P0.7-B,P2.0-S2,P0.5-S3,P0.3-S1********/
u8 code ledDuan[16] = {0x20,0x6E,0x50,0x44,0x0E,0x84,0x80,0x6C,0x00,0x04,//0-9
0xFE,0xB0,0x90,0x98, 0xDA,0xB2}; //NULL,C,E,F,r,L
/***********************温度表,扩大10倍**********************************************************/
u16 code ntcPositive[250] =
{ 77, 82, 86, 91, 95, 101, 106, 111, 117, 123, //1~10
130, 136, 143, 151, 158, 166, 174, 183, 192, 201, //11~20
211, 221, 232, 243, 255, 267, 279, 292, 305, 319, //21~30
334, 349, 365, 381, 398, 415, 433, 452, 471, 491, //31~40
512, 534, 556, 579, 602, 627, 652, 678, 705, 733, //41~50
761, 791, 821, 853, 885, 918, 952, 987, 1023,1059, //51~60
1097,1136,1176,1217,1258,1301,1345,1390,1436,1483, //61~70
1530,1579,1629,1680,1732,1785,1839,1894,1950,2007, //71~80
2064,2123,2183,2243,2305,2367,2431,2495,2559,2625, //81~90
2692,2759,2827,2895,2964,3034,3105,3176,3247,3319, //91~100
3392,3465,3538,3612,3686,3761,3835,3910,3985,4061, //101~110
4136,4211,4287,4363,4438,4514,4589,4664,4740,4815, //111~120
4889,4964,5038,5112,5186,5259,5332,5404,5476,5548, //121~130
5619,5689,5759,5829,5898,5966,6034,6101,6167,6233, //131~140
6298,6363,6426,6489,6552,6613,6674,6734,6793,6852, //141~150
6910,6967,7023,7079,7134,7188,7241,7293,7345,7396, //151~160
7446,7496,7544,7592,7639,7686,7731,7776,7820,7864, //161~170
7906,7948,7990,8030,8070,8109,8148,8186,8223,8259, //171~180
8295,8330,8365,8399,8432,8465,8497,8529,8560,8590, //181~190
8620,8649,8678,8706,8734,8761,8787,8814,8839,8864, //191~200
8889,8913,8937,8960,8983,9005,9027,9049,9070,9091, //201~210
9111,9131,9151,9170,9189,9207,9225,9243,9260,9277, //211~220
9294,9310,9327,9342,9358,9373,9388,9402,9417,9431, //221~230
9445,9458,9471,9484,9497,9510,9522,9534,9546,9557, //231~240
9569,9580,9591,9601,9612,9622,9632,9642,9652,9662, //241-250
};
/*********对应段里的位置************************************************************************/
#define NUL 10
#define C 11
#define E 12
#define F 13
#define r 14
#define L 15
sbit PTC=P1^0 ;
bit bCf=0;
bit bPowerOn=0;
u8 errNtc=0;
u8 realTemp=1;
/*********************************************************************************/
/***************************************************************************************
***************************************************************************************/
/*********端口设置************************************************************************/
void GPIOSysInit(void)
{
P0M1 = 0x88;
P0M2 = 0x88;
P0M3 = 0x88;
P2M0 = 0x88;
P2M1 = 0x88;
P2M2 = 0x88;
P2M3 = 0x88;
}
/**************看门狗设置*******************************************************************/
void IWDG_Init(void)
{
/***********************************WDT配置初始化**************************************/
WDTC = 0x57; //允许WDT复位,允许掉电/空闲模式下运行,1024分频
//WDT使用的是RC44K时钟,WDT_CLOCK_1024是1024分频,初值为0xFF
//定时时间 = 1024 * 0xFF / 44000
// = 5.93s
WDTCCR = 0xFF; //写入00时,将关闭WDT功能(但不关闭内部低频RC),
//即相当于禁止WDT。写入非0数据时,将启动WDT。
}
/*****************喂狗***********************************************************/
void CLRWDT(void)
{
WDTC |= 0x10; //喂狗
}
/************ADC设置*********************************************************************/
void ADC_Init(void)
{ /************************************ADC初始化*****************************************/
P0M0 = P0M0|0x03; //P00设置为模拟输入
ADCC0 = 0x80; //打开ADC转换电源
ADCC1 = 0x00; //选择外部通道0
ADCC2 = 0xCD; //转换结果10位数据,数据右对齐,ADC时钟16分频 ,1MHz
ADCC0 |= 0x40; //启动ADC转换
}
/*****************延时***********************************************************/
void Delayus(u8 us)
{
u8 i,j;
for(i=0; i<us; i++)
for(j=0; j<10; j++);
}
/*****************数码管显示***********************************************************/
void LedDisplay(u8 *dat)
{
u8 buff[4],i;
CLRWDT();
for(i=0; i<4; i++)
buff = *dat++;
P0_3=1;
P2_0=0;
P0_5=0;
P2= (P2&0XC1)|((ledDuan[buff[0]])&0x3E);
P0= (P0&0X3F)|((ledDuan[buff[0]])&0xC0);
Delayus(200);
P2= 0XFE;
P0= 0XC0;
P0_3=0;
P2_0=1;
P0_5=0;
if(buff[3] == F)
P2_6= 0;
else
P2_6= 1;
P2= (P2&0XC1)|((ledDuan[buff[1]])&0x3E);
P0= (P0&0X3F)|((ledDuan[buff[1]])&0xC0);
Delayus(200);
P2= 0XFE;
P0= 0XC0;
P0_3=0;
P2_0=0;
P0_5=1;
if(buff[3] == C)
P2_6= 0;
else
P2_6= 1;
P2= (P2&0XC1)|((ledDuan[buff[2]])&0x3E);
P0= (P0&0X3F)|((ledDuan[buff[2]])&0xC0);
Delayus(200);
P2= 0XFE;
P0= 0XC0;
}
/***************温度显示*************************************************************/
void DisplayTmp(u16 dat)
{
u8 tmp[4];
CLRWDT();
tmp[0] = dat/100;
tmp[1] = dat/10%10;
// tmp[1]=tmp[1]%10;
tmp[2] = dat%10;
if(dat < 100)
{
tmp[0] = NUL;
if(dat<10)
tmp[1] = NUL;
}
if(bCf)
tmp[3] = F;
else
tmp[3] = C;
LedDisplay(tmp);
}
/***************检测温度******************************************************************/
void AdcSampling(void)
{
u8 i=0;
static u8 j=0,p=0;
static u16 sum=0,k=0;
CLRWDT();
if(ADCC0&0x20)//ADC转换中断
{
ADCC0 &=~ 0x20; //清除标志位
if(j > 49) //50次
{
sum=sum/5;
j = 0;
if(sum >10000) // < 0 故障
{
k=0;
//if(!bPowerOn)//开机时
{
p++;
if(p > 20) //2s
{
p = 0;
errNtc = 1;//NTC 短路
}
}
//else
{
// k=0;
// p=0;
// j=0;
}
}
else if(sum <20)
{
p=0;
//if(!bPowerOn)//开机时
{
k++;
if(k > 1050) //30s
{
k = 0;
errNtc = 2;//NTC 开路
}
}
//else
{
// k=0;
// j=0;
}
}
else//无故障
{
if(sum<77)
realTemp = 0;
if(sum>9557)
realTemp =240;
for(i=0; i<241; i++)//查询温度
{
if(sum < (ntcPositive))
{
realTemp = i;
if(realTemp >= 240)//温度超限
realTemp = 240;
break;
}
}
errNtc = 0;//故障解除
k = 0;
p=0;
}
sum=0;
}
else
{
j++;
sum+= ADCR; //获取ADC的值
}
ADCC0 |= 0x40; //启动ADC转换
}
}
/*************初始化********************************************************************/
void SystemInit(void)
{
/************************************系统初始化****************************************/
WDTCCR = 0x00; //关闭看门狗
while((CLKCON&0x20)!=0x20); //等待内部高频晶振起振
CLKSWR = 0x51; //选择内部高频时钟为主时钟,内部高频RC2分频,Fosc=16MHz
while((CLKSWR&0xC0)!=0x40); //等待内部高频切换完成
CLKDIV = 0x01; //Fosc1分频得到Fcpu,Fcpu=16MHz
/***********************************************************************/
GPIOSysInit(); //端口初始化
ADC_Init();
//Tim1_Init();
IWDG_Init();
}
void main()
{
u8 tmp[4];
//u16 data dat;
SystemInit(); //系统初始化
while(1)
{
CLRWDT();
AdcSampling();//检测温度
if(errNtc!=0)//故障时
{
tmp[0] = E;
tmp[1] = r;
tmp[2] = r;
tmp[3] = NUL;
LedDisplay(tmp);//Err
}
else
DisplayTmp(realTemp);
}
}
|
|