可以将光照值和温度值显示在数码管上(AD转换)
单片机源程序如下:
- #include <reg52.h>
- #include <intrins.h>
- sfr P0M1 = 0x93;
- sfr P0M0 = 0x94;
- sfr P2M1 = 0x95;
- sfr P2M0 = 0x96;
- sfr CLK_DIV = 0x97;
- //sfr AUXR = 0x8E;
- sfr ADC_CONTR = 0xBC; //ADC控制寄存器
- sfr ADC_RES = 0xBD; //ADC高8位结果
- sfr ADC_LOW2 = 0xBE; //ADC低2位结果
- sfr P1ASF = 0x9D; //P1口模拟功能控制寄存器
- #define ADC_POWER 0x80 //ADC电源控制位
- #define ADC_FLAG 0x10 //ADC完成标志
- #define ADC_START 0x08 //ADC起始控制位
- #define ADC_SPEEDLL 0x00 //540个时钟
- #define ADC_SPEEDL 0x20 //360个时钟
- #define ADC_SPEEDH 0x40 //180个时钟
- #define ADC_SPEEDHH 0x60 //90个时钟
- sbit LED_SEL = P2^3;
- sbit BEEP = P3^4;
- unsigned char code LedChar[] = { //数码管显示字符转换表 0-F
- 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,
- 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71
- };
- unsigned char LedBuff[9] = { //数码管显示缓冲区 + 独立LED缓冲区
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- int code TempData[]={
- 239,197,175,160,150,142,135,129,124,120,116,113,109,107,104,101, //温度值对应表
- 99, 97, 95, 93, 91, 90, 88, 86, 85, 84, 82, 81, 80, 78, 77, 76,
- 75, 74, 73, 72, 71, 70, 69, 68, 67, 67, 66, 65, 64, 63, 63, 62,
- 61, 61, 60, 59, 58, 58, 57, 57, 56, 55, 55, 54, 54, 53, 52, 52,
- 51, 51, 50, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45, 45, 44, 44,
- 43, 43, 42, 42, 41, 41, 41, 40, 40, 39, 39, 38, 38, 38, 37, 37,
- 36, 36, 36, 35, 35, 34, 34, 34, 33, 33, 32, 32, 32, 31, 31, 31,
- 30, 30, 29, 29, 29, 28, 28, 28, 27, 27, 27, 26, 26, 26, 25, 25,
- 24, 24, 24, 23, 23, 23, 22, 22, 22, 21, 21, 21, 20, 20, 20, 19,
- 19, 19, 18, 18, 18, 17, 17, 16, 16, 16, 15, 15, 15, 14, 14, 14,
- 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, 9, 9, 9, 8, 8, 8, 7,
- 7, 7, 6, 6,5, 5, 54,4, 3, 3,3, 2, 2, 1, 1, 1, 0, 0, -1, -1, -1,
- -2, -2, -3, -3, -4, -4, -5, -5, -6, -6, -7, -7, -8, -8, -9, -9,
- -10, -10, -11, -11, -12, -13, -13, -14, -14, -15, -16, -16, -17,
- -18, -19, -19, -20, -21, -22, -23, -24, -25, -26, -27, -28, -29,
- 30, -32, -33, -35, -36, -38, -40, -43, -46, -50, -55, -63, 361
- };
- unsigned char ch = 3; //ADC通道号
- int temp = 0;
- unsigned int light = 0;
- unsigned char T0RH = 0; //T0重载值的高字节
- unsigned char T0RL = 0; //T0重载值的低字节
- bit beep_flag = 0; //蜂鸣器运行控制位
- void InitADC();
- void Delay2ms();
- void ConfigTimer0(unsigned int ms);
- void main()
- {
- P0M0 = 0xFF;
- P0M1 = 0x00;
- P2M0 = 0x08;
- P2M1 = 0x00;
-
- LED_SEL = 0;
-
- InitADC(); //初始化ADC
- IE = 0xA0; //使能ADC中断
- //开始AD转换
- ConfigTimer0(1); //配置T0定时1ms
-
- while(1)
- {
- if (temp < 0)
- {
- LedBuff[0] = 0x40;
- LedBuff[1] = LedChar[-temp/10%10];
- LedBuff[2] = LedChar[-temp%10];
- }
- else
- {
- LedBuff[0] = LedChar[temp/100%10];
- LedBuff[1] = LedChar[temp/10%10];
- LedBuff[2] = LedChar[temp%10];
- }
-
- LedBuff[5] = LedChar[light/100%10];
- LedBuff[6] = LedChar[light/10%10];
- LedBuff[7] = LedChar[light%10];
-
- if (temp >= 28)
- {
- beep_flag = 1;
- LedBuff[8] = 0xFF;
- }
- else
- {
- LedBuff[8] = 0x01;
- }
- }
- }
- /* ADC中断服务程序 */
- void adc_isr() interrupt 5 using 1
- {
- static unsigned int cnt = 0; //记录ADC中断次数
- static unsigned long temp_sum = 0; //温度AD值累加和
- static unsigned long light_sum = 0; //光照AD值累加和
-
- cnt++; //中断次数+1
- ADC_CONTR &= !ADC_FLAG; //清除ADC中断标志
-
- if (ch == 3)
- {
- temp_sum += (ADC_RES*256+ADC_LOW2)/4;
- }
- if (ch == 4)
- {
- light_sum += ADC_RES*256+ADC_LOW2;
- }
-
- if (cnt > 2000)
- {
- cnt = 0;
-
- temp = TempData[(temp_sum+1000/2)/1000-1];
- light = (light_sum+1000/2)/1000;
- temp_sum = 0;
- light_sum = 0;
- }
-
- ADC_RES = 0;
- ADC_LOW2 = 0; //清除结果寄存器
-
- if (++ch == 5) ch=3; //切换到下一个通道
- ADC_CONTR = ADC_POWER|ADC_SPEEDLL|ADC_START|ch;
- CLK_DIV = 0x20;
- }
- /* 初始化ADC */
- void InitADC()
- {
- P1ASF = 0xFF; //设置P1口为AD口
- ADC_RES = 0;
- ADC_LOW2 = 0; //清除结果寄存器
- ADC_CONTR = ADC_POWER|ADC_SPEEDLL|ADC_START|ch;
- CLK_DIV = 0x20; //ADC_RES[1:0]存放高2位ADC结果,ADC_RESL[7:0]存放低8位ADC结果
- Delay2ms(); //ADC上电并延时
- }
- void Delay2ms() //@11.0592MHz
- {
- unsigned char i, j;
- _nop_();
- _nop_();
- i = 22;
- j = 128;
- do
- {
- while (--j);
- } while (--i);
- }
- /* 配置并启动T0,ms为T0定时时间 */
- void ConfigTimer0(unsigned int ms)
- {
- unsigned long tmp; //临时变量
-
- tmp = 11059200 / 12; //定时器计数频率
- tmp = (tmp * ms) / 1000; //计算所需的计数值
- tmp = 65536 - tmp; //计算定时器重载值
- tmp = tmp + 13; //补偿中断响应延时造成的误差
- T0RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节
- T0RL = (unsigned char)tmp;
- TMOD &= 0xF0; //清零T0的控制位
- TMOD |= 0x01; //配置T0为模式1
- TH0 = T0RH; //加载T0重载值
- TL0 = T0RL;
- ET0 = 1; //使能T0中断
- TR0 = 1; //启动T0
- }
- /* LED动态扫描函数,需在定时中断中调用 */
- void LedScan()
- {
- static unsigned char i = 0; //动态扫描索引
-
- P0 = 0x00; //关闭所有段选位,显示消隐
- P2 = (P2 & 0xF0) | i; //位选索引值赋值到P2口低3位
- P0 = LedBuff[i]; //缓冲区中索引位置的数据送到P0口
- if (i < sizeof(LedBuff)-1) //索引递增循环,遍历整个缓冲区
- i++;
- else
- i = 0;
- }
- /* T0中断服务函数,完成数码管扫描 */
- void InterruptTimer0() interrupt 1
- {
- static unsigned int cnt = 0;
- TH0 = T0RH; //重新加载重载值
- TL0 = T0RL;
- LedScan(); //LED扫描显示
-
- if (beep_flag)
- {
- BEEP = ~BEEP; //反转蜂鸣器控制电平
- cnt++;
- if (cnt > 5000) { //中断5000次后,即定时5ms
- cnt = 0;
- beep_flag = 0;
- }
- }
- }
复制代码
所有资料51hei提供下载:
lesson5.zip
(39.54 KB, 下载次数: 11)
|