通过STC15W4k56S4单片机中8通道10位高速电压输入型模拟数字转换器(ADC)配置,用于温度、电池电压、距离、频谱等的检测和按键扫描。本任务实现实验板测定芯片外部光敏传感器的电压值,并通过串口发送电压值。
具体步骤为:实验板上电后,初始化串口1和ADC;开启ADC通道0,对直流电压值进行采集;串口助手接收测量电压值,例如“2.7V”重复上述步骤。
知识引入
符号 | 描述 | 地址 | 位地址及其符号 MSB LSB |
复位值 |
P1ASF | 模拟输入通道功能控制寄存器 | 9DH | PI7ASF|PI6ASF|PI5ASF|PI4ASF|PI3ASF|PI2ASF|PI1ASF|PI0ASF| | 0000 0000B |
ADC_CONTR | ADC控制寄存器 | BCH | ADC_POWER|SPEED1|SPEED0|ADC_FLAG|ADC_START|CHS2|CHS1|CHS0 | 0000 0000B |
ADC_RES | A/D转换结果寄存器 | BDH | A/D转换结果寄存器 | 0000 0000B |
ADC_RESL | A/D转换结果寄存器 | BEH | A/D转换结果寄存器 | 0000 0000B |
CLK_DIV (PCON2) |
时钟分频寄存器 | 97H | SysCKO_S1|SysCKO_S0|ADRJ|Tx_Rx|SysClKS2|CLKS1|CLKS0 | 0000 0000B |
IE | 中断允许控制 | A8H | EA | ELVD | EADC | ES | ET1 | EX1 | ET0 | EX0 | 0000 0000H |
IP | 中断优先级控制 | B8H | PPCA | PLVD | PADC | PS | PT1 | PX1 | PT0 | PX0 | 0000 0000H |
SPEED1 | SPEED0 | A/D转换一次所需时间 |
1 | 1 | 90个时钟周期 |
1 | 0 | 180个时钟周期 |
0 | 1 | 360个时钟周期 |
0 | 0 | 540个时钟周期 |
CHS2 | CHS1 | CHS0 | 模拟输入通道选择 |
0 | 0 | 0 | 选择ADC0(P1.0)作为A/D输入 |
0 | 0 | 1 | 选择ADC1(P1.1)作为A/D输入 |
0 | 1 | 0 | 选择ADC2(P1.2)作为A/D输入 |
0 | 1 | 1 | 选择ADC3(P1.3)作为A/D输入 |
1 | 0 | 0 | 选择ADC4(P1.4)作为A/D输入 |
1 | 0 | 1 | 选择ADC5(P1.5)作为A/D输入 |
1 | 1 | 0 | 选择ADC6(P1.6)作为A/D输入 |
1 | 1 | 1 | 选择ADC7(P1.7)作为A/D输入 |
#include <STC15.h> #include "intrins.h" #include "stdio.h" #define FOSC 11059200 #define BAUD 9600 typedef unsigned char BYTE; typedef unsigned int WORD; #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个时钟 void InitUart(); void SendData(BYTE dat); void Delay(WORD n); void InitADC(); void ShowResult(void); BYTEgewei,shifen;//定义电压输出值的个位和小数点后面第一位 BYTE ch = 0; //ADC通道号 WORD adc_result;//定义10位AD采集结果值 void main() { InitUart(); //初始化串口 InitADC(); //初始化ADC IE = 0xa0; //使能ADC中断 while (1) { ShowResult(); //显示通道1 Delay(150);//延迟 } } /*---------------------------- ADC中断服务程序 ----------------------------*/ void adc_isr() interrupt 5 using 1 { ADC_CONTR &= !ADC_FLAG; //清除ADC中断标志 adc_result=ADC_RES*256+ADC_RESL; ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch; } /*---------------------------- 初始化ADC ----------------------------*/ void InitADC() { P1ASF = 0x01; //设置P1口为AD口 CLK_DIV |=0x20; ADC_RES = 0; //清除结果寄存器 ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch; Delay(2); //ADC上电并延时 } /*---------------------------- 初始化串口 ----------------------------*/ void InitUart() { SCON = 0x5a; //设置串口为8位可变波特率 TMOD = 0x20; //设置定时器1为8位自动重装载模式 AUXR = 0x40; //定时器1为1T模式 TH1 = TL1 = 0xDC; //9600 bps(256 - 11059200/32/9600) TR1 = 1; } /*---------------------------- 发送ADC结果到PC ,例如2.7V ----------------------------*/ void ShowResult(void) { gewei=adc_result%1000%100/10; shifen=adc_result%1000%100%10; SendData(gewei+0x30); //显示个位的电压数值 SendData(0x2E); //显示小数点 SendData(shifen+0x30); //显示十分位位上的电压数值 SendData(0x56); //显示"V" SendData(0x0d); // SendData(0x0a); //回车 } /*---------------------------- 发送串口数据 ----------------------------*/ void SendData(BYTE dat) { while (!TI); //等待前一个数据发送完成 TI = 0; //清除发送标志 SBUF = dat; //发送当前数据 } /*---------------------------- 软件延时 ----------------------------*/ void Delay(WORD n) { WORD x; while (n--) { x = 5000; while (x--); } }/*---------------------------- 软件延时 ----------------------------*/ void Delay(WORD n) { WORD x; while (n--) { x = 5000; while (x--); } } |