- /*---------------------------------------------------------------------*/
- /* --- STC MCU Limited ------------------------------------------------*/
- /* --- STC 1T Series MCU Demo Programme -------------------------------*/
- /* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序 */
- /*---------------------------------------------------------------------*/
- /************* 本程序功能说明 **************
- 本例程基于STC8H8K64U为主控芯片的实验箱9进行编写测试,STC8G、STC8H系列芯片可通用参考.
- 读ADC和测温度.
- 用STC的MCU的IO方式驱动8位数码管。
- 使用Timer0的16位自动重装来产生1ms节拍,程序运行于这个节拍下,用户修改MCU主时钟频率时,自动定时于1ms.
- 右边4位数码管显示温度值, 分辨率0.1度.
- NTC使用1%精度的MF52 10K@25度.
- 测温度时, 使用12位的ADC值, 使用对分查找表格来计算, 小数点后一位数是用线性插补来计算的.
- 下载时, 选择时钟 24MHZ (用户可自行修改频率).
- ******************************************/
- #include "reg51.h" //包含此头文件后,里面声明的寄存器不需要再手动输入,避免重复定义
- #include "intrins.h"
- #define MAIN_Fosc 24000000L //定义主时钟
- typedef unsigned char u8;
- typedef unsigned int u16;
- typedef unsigned long u32;
- //手动输入声明"reg51.h"头文件里面没有定义的寄存器
- sfr TH2 = 0xD6;
- sfr TL2 = 0xD7;
- sfr IE2 = 0xAF;
- sfr INT_CLKO = 0x8F;
- sfr AUXR = 0x8E;
- sfr AUXR1 = 0xA2;
- sfr P_SW1 = 0xA2;
- sfr P_SW2 = 0xBA;
- sfr S2CON = 0x9A;
- sfr S2BUF = 0x9B;
- sfr ADC_CONTR = 0xBC; //带AD系列
- sfr ADC_RES = 0xBD; //带AD系列
- sfr ADC_RESL = 0xBE; //带AD系列
- sfr ADCCFG = 0xde;
- sfr P4 = 0xC0;
- sfr P5 = 0xC8;
- sfr P6 = 0xE8;
- sfr P7 = 0xF8;
- sfr P1M1 = 0x91; //PxM1.n,PxM0.n =00--->Standard, 01--->push-pull
- sfr P1M0 = 0x92; // =10--->pure input, 11--->open drain
- sfr P0M1 = 0x93;
- sfr P0M0 = 0x94;
- sfr P2M1 = 0x95;
- sfr P2M0 = 0x96;
- sfr P3M1 = 0xB1;
- sfr P3M0 = 0xB2;
- sfr P4M1 = 0xB3;
- sfr P4M0 = 0xB4;
- sfr P5M1 = 0xC9;
- sfr P5M0 = 0xCA;
- sfr P6M1 = 0xCB;
- sfr P6M0 = 0xCC;
- sfr P7M1 = 0xE1;
- sfr P7M0 = 0xE2;
- sbit P00 = P0^0;
- sbit P01 = P0^1;
- sbit P02 = P0^2;
- sbit P03 = P0^3;
- sbit P04 = P0^4;
- sbit P05 = P0^5;
- sbit P06 = P0^6;
- sbit P07 = P0^7;
- sbit P10 = P1^0;
- sbit P11 = P1^1;
- sbit P12 = P1^2;
- sbit P13 = P1^3;
- sbit P14 = P1^4;
- sbit P15 = P1^5;
- sbit P16 = P1^6;
- sbit P17 = P1^7;
- sbit P20 = P2^0;
- sbit P21 = P2^1;
- sbit P22 = P2^2;
- sbit P23 = P2^3;
- sbit P24 = P2^4;
- sbit P25 = P2^5;
- sbit P26 = P2^6;
- sbit P27 = P2^7;
- sbit P30 = P3^0;
- sbit P31 = P3^1;
- sbit P32 = P3^2;
- sbit P33 = P3^3;
- sbit P34 = P3^4;
- sbit P35 = P3^5;
- sbit P36 = P3^6;
- sbit P37 = P3^7;
- sbit P40 = P4^0;
- sbit P41 = P4^1;
- sbit P42 = P4^2;
- sbit P43 = P4^3;
- sbit P44 = P4^4;
- sbit P45 = P4^5;
- sbit P46 = P4^6;
- sbit P47 = P4^7;
- sbit P50 = P5^0;
- sbit P51 = P5^1;
- sbit P52 = P5^2;
- sbit P53 = P5^3;
- sbit P54 = P5^4;
- sbit P55 = P5^5;
- sbit P56 = P5^6;
- sbit P57 = P5^7;
- /****************************** 用户定义宏 ***********************************/
- #define ADCTIM (*(unsigned char volatile xdata *)0xfea8)
- #define Timer0_Reload (65536UL -(MAIN_Fosc / 1000)) //Timer 0 中断频率, 1000次/秒
- /*****************************************************************************/
- #define DIS_DOT 0x20
- #define DIS_BLACK 0x10
- #define DIS_ 0x11
- /************* 本地常量声明 **************/
- u8 code t_display[]={ //标准字库
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
- 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
- //black - H J K L N o P U t G Q r M y
- 0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
- 0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
- u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码
- /************* 本地变量声明 **************/
- u8 LED8[8]; //显示缓冲
- u8 display_index; //显示位索引
- bit B_1ms; //1ms标志
- u16 msecond;
- /************* 本地函数声明 **************/
- u16 get_temperature(u16 adc);
- u16 Get_ADC12bitResult(u8 channel); //channel = 0~15
- /**********************************************/
- void main(void)
- {
- u8 i;
- u16 j;
-
- P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
- P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
- P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
- P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
- P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
- P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
- P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
- P1M1 = 0x08; P1M0 = 0x00; //设置 P1.3 为 ADC 输入口
- display_index = 0;
- P_SW2 |= 0x80;
- ADCTIM = 0x3f; //设置 ADC 内部时序,ADC采样时间建议设最大值
- P_SW2 &= 0x7f;
- ADCCFG = 0x2f; //设置 ADC 时钟为系统时钟/2/16/16
- ADC_CONTR = 0x80; //使能 ADC 模块
- AUXR = 0x80; //Timer0 set as 1T, 16 bits timer auto-reload,
- TH0 = (u8)(Timer0_Reload / 256);
- TL0 = (u8)(Timer0_Reload % 256);
- ET0 = 1; //Timer0 interrupt enable
- TR0 = 1; //Tiner0 run
- EA = 1; //打开总中断
-
- for(i=0; i<8; i++) LED8[i] = 0x10; //上电消隐
-
- while(1)
- {
- if(B_1ms) //1ms到
- {
- B_1ms = 0;
- if(++msecond >= 300) //300ms到
- {
- msecond = 0;
-
- j = Get_ADC12bitResult(3); //参数0~15,查询方式做一次ADC, 返回值就是结果, == 4096 为错误
- if(j < 4096)
- {
- /*
- LED8[0] = j / 1000; //显示ADC值
- LED8[1] = (j % 1000) / 100;
- LED8[2] = (j % 100) / 10;
- LED8[3] = j % 10;
- if(LED8[0] == 0) LED8[0] = DIS_BLACK;
- */
- j = get_temperature(j); //计算温度值
- if(j >= 400) F0 = 0, j -= 400; //温度 >= 0度
- else F0 = 1, j = 400 - j; //温度 < 0度
- LED8[4] = j / 1000; //显示温度值
- LED8[5] = (j % 1000) / 100;
- LED8[6] = (j % 100) / 10 + DIS_DOT;
- LED8[7] = j % 10;
- if(LED8[4] == 0) LED8[4] = DIS_BLACK;
- if(F0) LED8[4] = DIS_; //显示-
- }
- else //错误
- {
- for(i=0; i<8; i++) LED8[i] = DIS_;
- }
- }
- }
- }
- }
- /**********************************************/
- //========================================================================
- // 函数: u16 Get_ADC12bitResult(u8 channel)
- // 描述: 查询法读一次ADC结果.
- // 参数: channel: 选择要转换的ADC.
- // 返回: 12位ADC结果.
- // 版本: V1.0, 2012-10-22
- //========================================================================
- u16 Get_ADC12bitResult(u8 channel) //channel = 0~15
- {
- ADC_RES = 0;
- ADC_RESL = 0;
- ADC_CONTR = (ADC_CONTR & 0xF0) | 0x40 | channel; //启动 AD 转换
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- while((ADC_CONTR & 0x20) == 0) ; //wait for ADC finish
- ADC_CONTR &= ~0x20; //清除ADC结束标志
- return (((u16)ADC_RES << 8) | ADC_RESL);
- }
- // MF52E 10K at 25, B = 3950, ADC = 12 bits
- u16 code temp_table[]={
- 140, //;-40 0
- 149, //;-39 1
- 159, //;-38 2
- 168, //;-37 3
- 178, //;-36 4
- 188, //;-35 5
- 199, //;-34 6
- 210, //;-33 7
- 222, //;-32 8
- 233, //;-31 9
- 246, //;-30 10
- 259, //;-29 11
- 272, //;-28 12
- 286, //;-27 13
- 301, //;-26 14
- 317, //;-25 15
- 333, //;-24 16
- 349, //;-23 17
- 367, //;-22 18
- 385, //;-21 19
- 403, //;-20 20
- 423, //;-19 21
- 443, //;-18 22
- 464, //;-17 23
- 486, //;-16 24
- 509, //;-15 25
- 533, //;-14 26
- 558, //;-13 27
- 583, //;-12 28
- 610, //;-11 29
- 638, //;-10 30
- 667, //;-9 31
- 696, //;-8 32
- 727, //;-7 33
- 758, //;-6 34
- 791, //;-5 35
- 824, //;-4 36
- 858, //;-3 37
- 893, //;-2 38
- 929, //;-1 39
- 965, //;0 40
- 1003, //;1 41
- 1041, //;2 42
- 1080, //;3 43
- 1119, //;4 44
- 1160, //;5 45
- 1201, //;6 46
- 1243, //;7 47
- 1285, //;8 48
- 1328, //;9 49
- 1371, //;10 50
- 1414, //;11 51
- 1459, //;12 52
- 1503, //;13 53
- 1548, //;14 54
- 1593, //;15 55
- 1638, //;16 56
- 1684, //;17 57
- 1730, //;18 58
- 1775, //;19 59
- 1821, //;20 60
- 1867, //;21 61
- 1912, //;22 62
- 1958, //;23 63
- 2003, //;24 64
- 2048, //;25 65
- 2093, //;26 66
- 2137, //;27 67
- 2182, //;28 68
- 2225, //;29 69
- 2269, //;30 70
- 2312, //;31 71
- 2354, //;32 72
- 2397, //;33 73
- 2438, //;34 74
- 2479, //;35 75
- 2519, //;36 76
- 2559, //;37 77
- 2598, //;38 78
- 2637, //;39 79
- 2675, //;40 80
- 2712, //;41 81
- 2748, //;42 82
- 2784, //;43 83
- 2819, //;44 84
- 2853, //;45 85
- 2887, //;46 86
- 2920, //;47 87
- 2952, //;48 88
- 2984, //;49 89
- 3014, //;50 90
- 3044, //;51 91
- 3073, //;52 92
- 3102, //;53 93
- 3130, //;54 94
- 3157, //;55 95
- 3183, //;56 96
- 3209, //;57 97
- 3234, //;58 98
- 3259, //;59 99
- 3283, //;60 100
- 3306, //;61 101
- 3328, //;62 102
- 3351, //;63 103
- 3372, //;64 104
- 3393, //;65 105
- 3413, //;66 106
- 3432, //;67 107
- 3452, //;68 108
- 3470, //;69 109
- 3488, //;70 110
- 3506, //;71 111
- 3523, //;72 112
- 3539, //;73 113
- 3555, //;74 114
- 3571, //;75 115
- 3586, //;76 116
- 3601, //;77 117
- 3615, //;78 118
- 3628, //;79 119
- 3642, //;80 120
- 3655, //;81 121
- 3667, //;82 122
- 3679, //;83 123
- 3691, //;84 124
- 3702, //;85 125
- 3714, //;86 126
- 3724, //;87 127
- 3735, //;88 128
- 3745, //;89 129
- 3754, //;90 130
- 3764, //;91 131
- 3773, //;92 132
- 3782, //;93 133
- 3791, //;94 134
- 3799, //;95 135
- 3807, //;96 136
- 3815, //;97 137
- 3822, //;98 138
- 3830, //;99 139
- 3837, //;100 140
- 3844, //;101 141
- 3850, //;102 142
- 3857, //;103 143
- 3863, //;104 144
- 3869, //;105 145
- 3875, //;106 146
- 3881, //;107 147
- 3887, //;108 148
- 3892, //;109 149
- 3897, //;110 150
- 3902, //;111 151
- 3907, //;112 152
- 3912, //;113 153
- 3917, //;114 154
- 3921, //;115 155
- 3926, //;116 156
- 3930, //;117 157
- 3934, //;118 158
- 3938, //;119 159
- 3942 //;120 160
- };
- /******************** 计算温度 ***********************************************/
- // 计算结果: 0对应-40.0度, 400对应0度, 625对应25.0度, 最大1600对应120.0度.
- // 为了通用, ADC输入为12bit的ADC值.
- // 电路和软件算法设计: Coody
- /**********************************************/
- #define D_SCALE 10 //结果放大倍数, 放大10倍就是保留一位小数
- u16 get_temperature(u16 adc)
- {
- u16 code *p;
- u16 i;
- u8 j,k,min,max;
-
- adc = 4096 - adc; //Rt接地
- p = temp_table;
- if(adc < p[0]) return (0xfffe);
- if(adc > p[160]) return (0xffff);
-
- min = 0; //-40度
- max = 160; //120度
- for(j=0; j<5; j++) //对分查表
- {
- k = min / 2 + max / 2;
- if(adc <= p[k]) max = k;
- else min = k;
- }
- if(adc == p[min]) i = min * D_SCALE;
- else if(adc == p[max]) i = max * D_SCALE;
- else // min < temp < max
- {
- while(min <= max)
- {
- min++;
- if(adc == p[min]) {i = min * D_SCALE; break;}
- else if(adc < p[min])
- {
- min--;
- i = p[min]; //min
- j = (adc - i) * D_SCALE / (p[min+1] - i);
- i = min;
- i *= D_SCALE;
- i += j;
- break;
- }
- }
- }
- return i;
- }
- /********************** 显示扫描函数 ************************/
- void DisplayScan(void)
- {
- P7 = ~T_COM[7-display_index];
- P6 = ~t_display[LED8[display_index]];
- if(++display_index >= 8) display_index = 0; //8位结束回0
- }
- /********************** Timer0 1ms中断函数 ************************/
- void timer0 (void) interrupt 1
- {
- DisplayScan(); //1ms扫描显示一位
- B_1ms = 1; //1ms标志
- }
复制代码
|