📄 text22.c
字号:
#include <absacc.h>
#include <reg51.h>
/*////////////////////////////*/
/*/ 常量定义 /*/
/*////////////////////////////*/
/* 定时器初值 */
#define V_T1 0xfd /*SCOM 9600 baud, ! notice: crystal 11.0592MHz */
#define V_TH0 0xee /* ~ 5ms , ! notice: crystal 11.0592MHz */
#define V_TL0 0x00
/* 数码管段驱动寄存器地址 */
#define ADDR_8SEG XBYTE[0x2000]
/* 数码管位驱动和指示灯驱动寄存器地址 */
#define ADDR_SEL XBYTE[0x4000]
/* 单片机输出频率 */
#define PWM_FREQ 400
#define TOTAL_TIME (11059200/12/PWM_FREQ)
/* ADC0804的地址 */
#define ADDR_0804 XBYTE[0x6000]
/* 按键 */
sbit KEY1= P1^0;
sbit KEY2= P1^1;
sbit KEY3= P1^2;
sbit KEY4= P1^3;
/* 输出 */
sbit PWM_OUT= P3^5;
/* 按键采样相同判定个数 */
#define v_keycount 3
#define ADJUST_NUM 3
/*电压采样个数*/
#define AD_SMPL_NUM 20
/*多项式阶数*/
#define V_POLYNOMINAL 2
/*闭环控制延迟因子*/
#define CLC_DELAY 100
/*////////////////////////////*/
/*/ 变量定义 /*/
/*////////////////////////////*/
/* 按键状态标志和计数器 */
bit key1_flag;
bit key2_flag;
bit key3_flag;
bit key4_flag;
unsigned char key1_count;
unsigned char key2_count;
unsigned char key3_count;
unsigned char key4_count;
/* 按键当前状态和前一状态 */
bit cur_sample1;
bit pre_sample1;
bit cur_sample2;
bit pre_sample2;
bit cur_sample3;
bit pre_sample3;
bit cur_sample4;
bit pre_sample4;
/* 数码管位驱动和指示灯驱动信号输出缓存,定义了一个可位寻址的变量 */
unsigned char bdata output_sel;
sbit led_1 = output_sel^5;
sbit led_2 = output_sel^6;
sbit led_3 = output_sel^7;
sbit led_4 = output_sel^4;
/* 数码管扫描驱动指针,为测试外部存储器(U3 6264),特使用xdata类型 */
unsigned char xdata digi_scaner;
/* 测试用计数值十进制表示,为测试外部存储器(U3 6264),特使用xdata类型 */
unsigned char xdata digi[4];
/*系统输出电压*/
unsigned int volt;
/* 单片机输出信号占空比 */
int prop_int;
float prop_float;
/*设定和显示状态标志*/
unsigned char setting_flag;
bit refresh_flag;
bit change_flag;
/*自动拟合参数*/
unsigned char adjust_count;
unsigned int adjust_Prop[ADJUST_NUM+1];
/*定时器1重装值变量*/
unsigned int hilv_time;
unsigned int lolv_time;
unsigned int hilv_th;
unsigned int hilv_tl;
unsigned int lolv_th;
unsigned int lolv_tl;
bit PWM_flag;
/*pv多项式变量*/
float coe_pv[V_POLYNOMINAL+1];
/*临时贮存用变量*/
unsigned char i,j;
/* 模数转换部分变量定义 */
bit AD_flag;
unsigned char xdata AD_data[AD_SMPL_NUM];
unsigned char AD_ptr;
unsigned int xdata AD_value;
unsigned int xdata AD_require;
int xdata AD_temp;
/* 开\闭环控制变量 */
bit CLC_flag;
unsigned char DelayCounter;
/*////////////////////////////*/
/*/ 函数定义 /*/
/*////////////////////////////*/
/**** 7段数码显示译码
参数:
DATA: 需要显示的数字或符号;
返回值: 7段译码结果 ( D7~0 = PGFEDCBA )
*****/
unsigned char NUMTOSEG7(unsigned char DATA)
{ unsigned char AA;
switch (DATA)
{
case 0: AA=0xc0;break; /* '0' */
case 1: AA=0xf9;break; /* '1'and'i' */
case 2: AA=0xa4;break; /* '2' */
case 3: AA=0xb0;break; /* '3' */
case 4: AA=0x99;break; /* '4' */
case 5: AA=0x92;break; /* '5'and's' */
case 6: AA=0x82;break; /* '6' */
case 7: AA=0xf8;break; /* '7' */
case 8: AA=0x80;break; /* '8' */
case 9: AA=0x90;break; /* '9' */
case 10: AA=0x88;break; /* 'A'and'R' */
case 11: AA=0x83;break; /* 'B' */
case 12: AA=0xc6;break; /* 'C' */
case 13: AA=0xa1;break; /* 'D' */
case 14: AA=0x86;break; /* 'E' */
case 15: AA=0x8e;break; /* 'F' */
case 16: AA=0x40;break; /* '0.' */
case 17: AA=0x79;break; /* '1.' */
case 18: AA=0x24;break; /* '2.' */
case 19: AA=0x30;break; /* '3.' */
case 20: AA=0x19;break; /* '4.' */
case 21: AA=0x12;break; /* '5.' */
case 22: AA=0x02;break; /* '6.' */
case 23: AA=0x78;break; /* '7.' */
case 24: AA=0x00;break; /* '8.' */
case 25: AA=0x10;break; /* '9.' */
case 26: AA=0xc8;break; /* 'n' */
case 27: AA=0xce;break; /* 'r' */
case 28: AA=0x87;break; /* 't' */
case 29: AA=0xc1;break; /* 'u' */
case 30: AA=0x8c;break; /* 'p' */
case '-':AA=0xbf;break; /* 破折号,此处原误为0xdf,系04级王资凯同学指正*/
case '_':AA=0xf7;break; /* 下划线*/
case ' ':AA=0xff;break; /* 消隐*/
default: AA=0xff;
}
return(AA);
}
/*查找表函数:电压与对应ADC值查找表*/
unsigned int ad_change(unsigned int volt)
{ unsigned int AA;
switch (volt)
{
case 50: AA=255;break; /* '0' */
case 51: AA=254;break; /* '1'and'i' */
case 52: AA=250;break; /* '2' */
case 53: AA=247;break; /* '3' */
case 54: AA=243;break; /* '4' */
case 55: AA=240;break; /* '5'and's' */
case 56: AA=235;break; /* '6' */
case 57: AA=231;break; /* '7' */
case 58: AA=227;break; /* '8' */
case 59: AA=223;break; /* '9' */
case 60: AA=219;break; /* '0' */
case 61: AA=214;break; /* '1'and'i' */
case 62: AA=210;break; /* '2' */
case 63: AA=205;break; /* '3' */
case 64: AA=201;break; /* '4' */
case 65: AA=197;break; /* '5'and's' */
case 66: AA=192;break; /* '6' */
case 67: AA=187;break; /* '7' */
case 68: AA=183;break; /* '8' */
case 69: AA=178;break; /* '9' */
case 70: AA=173;break; /* '0' */
case 71: AA=168;break; /* '1'and'i' */
case 72: AA=164;break; /* '2' */
case 73: AA=159;break; /* '3' */
case 74: AA=154;break; /* '4' */
case 75: AA=149;break; /* '5'and's' */
case 76: AA=144;break; /* '6' */
case 77: AA=139;break; /* '7' */
case 78: AA=134;break; /* '8' */
case 79: AA=128;break; /* '9' */
case 80: AA=123;break; /* '0' */
case 81: AA=118;break; /* '1'and'i' */
case 82: AA=113;break; /* '2' */
case 83: AA=108;break; /* '3' */
case 84: AA=102;break; /* '4' */
case 85: AA=97;break; /* '5'and's' */
case 86: AA=91;break; /* '6' */
case 87: AA=86;break; /* '7' */
case 88: AA=80;break; /* '8' */
case 89: AA=74;break; /* '9' */
case 90: AA=69;break; /* '0' */
case 91: AA=63;break; /* '1'and'i' */
case 92: AA=58;break; /* '2' */
case 93: AA=52;break; /* '3' */
case 94: AA=46;break; /* '4' */
case 95: AA=40;break; /* '5'and's' */
case 96: AA=34;break; /* '6' */
case 97: AA=27;break; /* '7' */
case 98: AA=22;break; /* '8' */
case 99: AA=16;break; /* '9' */
case 100: AA=10;break; /* '0' */
default: AA=0xff;
}
return(AA);
}
/**** T0时钟中断服务程序模块
每5ms被执行一次
*****/
timer0() interrupt 1 using 0
{
ET0=0; /*关中断*/
/* 重新对计数器赋初值,并启动定时计数 */
TH0=V_TH0;
TL0=V_TL0;
TR0=1;
/* 检测到按键被按下(0)时,相应的指示灯亮(0) */
if (KEY1==0) led_1 = 0;
if (KEY2==0) led_2 = 0;
if (KEY3==0) led_3 = 0;
if (KEY4==0) led_4 = 0;
/********************************/
/* 数码管扫描 */
/********************************/
output_sel = 0xf0; /*初值,令数码管驱动位无效,指示灯全灭*/
/* 数码管扫描驱动指针值从1到4重复变换,每5ms间隔对一个数码管进行驱动,20ms一个轮回 */
if (++digi_scaner>=5) digi_scaner = 1;
switch (digi_scaner)
{
case 1: /* 驱动第一个数码管 */
output_sel |= 0x01;
ADDR_8SEG = NUMTOSEG7(digi[0]); /*输出到锁存器U5*/
break;
case 2: /* 驱动第二个数码管 */
output_sel |= 0x02;
ADDR_8SEG = NUMTOSEG7(digi[1]); /*输出到锁存器U5*/
break;
case 3: /* 驱动第三个数码管 */
output_sel |= 0x04;
ADDR_8SEG = NUMTOSEG7(digi[2]); /*输出到锁存器U5*/
break;
case 4: /* 驱动第四个数码管 */
output_sel |= 0x08;
ADDR_8SEG = NUMTOSEG7(digi[3]); /*输出到锁存器U5*/
break;
}
ADDR_SEL = output_sel; /*输出到锁存器U6(在电路图中找)*/
/**********************************************
以下四段为消抖动程序,以第一个为例说明。
程序来自2005年4月22日科创讲座的笔记,袁焱老师提供。
********************************************/
/* 对按键一进行消抖 */
cur_sample1 = KEY1; /* 将按键一的当前状态读取到cur_sample1 */
if(pre_sample1 != cur_sample1) key1_count++;
else key1_count = 0; /* 如果按键的状态发生了改变,则开始计数,反之清零 */
if(key1_count >= v_keycount)/* 如果按键在改变的状态持续达到v_keycount的次数执行以下片断 */
{
key1_count = 0; /* 给出按键被按下的flag,计数器归零,默认状态置为当前状态 */
if(cur_sample1 == 0) key1_flag = 1;
pre_sample1 = cur_sample1;
}
/* 对按键二进行消抖,原理同按键一,见按键一的注释 */
cur_sample2 = KEY2;
if(pre_sample2 != cur_sample2) key2_count++;
else key2_count = 0;
if(key2_count >= v_keycount)
{
key2_count = 0;
if(cur_sample2 == 0) key2_flag = 1;
pre_sample2 = cur_sample2;
}
/* 对按键三进行消抖,原理同按键一,见按键一的注释 */
cur_sample3 = KEY3;
if(pre_sample3 != cur_sample3) key3_count++;
else key3_count = 0;
if(key3_count >= v_keycount)
{
key3_count = 0;
if(cur_sample3 == 0) key3_flag = 1;
pre_sample3 = cur_sample3;
}
/* 对按键四进行消抖,原理同按键一,见按键一的注释 */
cur_sample4 = KEY4;
if(pre_sample4 != cur_sample4) key4_count++;
else key4_count = 0;
if(key4_count >= v_keycount)
{
key4_count = 0;
if(cur_sample4 == 0) key4_flag = 1;
pre_sample4 = cur_sample4;
}
/*按键消抖程序结束*/
/*************************************
子模块:ADC部分程序,读取ADC的输出值
*************************************/
if(AD_flag==0)
{
if((++DelayCounter)<=30)
{
AD_data[AD_ptr] = ADDR_0804 ; // 读0804
AD_ptr++;
}
AD_flag = 1;
}
ET0=1; /*开中断*/
}
/*************************************
PMW信号发生模块,使用定时器1提供的中断
*************************************/
PwmGenerator() interrupt 3 using 1
{
EA=0;
TR1=1;
if(PWM_flag==0)
{ PWM_OUT=1;
TH1=hilv_th;
TL1=hilv_tl;
PWM_flag=1;
}
else
{
PWM_OUT=0;
TH1=lolv_th;
TL1=lolv_tl;
PWM_flag=0;
}
EA=1;
}
/*开环控制模块,计算v对应的p*/
void Calc_Prop(unsigned int volt)
{
EA=0;
switch (volt)
{
case 50: prop_float=196;break; /* '0' */
case 51: prop_float=203;break; /* '1'and'i' */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -