stc12c56 串口显示AD(单路ad+led指示灯)
//烧写程序时,一定要选用外部晶振(烧写软件默认为内部晶振(5M~6M))
//烧写时,有时候写不进去,尝试断开地线,然后接上上电
/*****************************************************
关于以下两个问题的说明
a=ADC_LOW2&0x03;//如果是dat=ADC_DATA<<2+ADC_LOW2&0x03;就会出错!莫名其妙!
dat=ADC_DATA*4+a; //如果是dat=ADC_DATA<<2+a 。就乱窜,一直飚过1024!而且串口老死!
从这两个问题可以看出,如果直接对某个8位寄存器进行操作,它会将中间产生的值,直接
放到该寄存器里,对于寄存器里的的数据不要直接操作,应该先读出来,在内存中处理数据 。
对寄存器的操作不要用<<、>>等等,也不要使用很长的公式(dat=ADC_DATA<<2+ADC_LOW2&0x03)
*****************************************************/
#include
#include
sfr ADC_CONTR = 0xc5;
sfr ADC_DATA =0xc6;
sfr ADC_LOW2 =0xbe;
sfr P1M0 =0x91;
sfr P1M1= 0x92;
sfr AUXR=0x8e;
//sfr AUXR1=0xA2;
//sfr BRT=0x9c;
sbit Led=P1^4;
#define ADC_POWER 0x80
#define ADC_FLAG 0x10
#define ADC_START 0x08
#define ADC_SPEEDLL 0x00
#define ADC_SPEEDL 0x20
#define ADC_SPEEDH 0x40 //这个速度,读出的数据噪声很大
#define ADC_SPEEDHH 0x60
#define RELOAD_COUNT 0xf3 //4M晶振,smod=0,9600bps 实际波特率=4000000/(256-243)/32=9615.误差=15/9600=0.16%
//具体计算看《STC12C5A60S2》第79页及其之后
unsigned char ch;
void serial_port_initial(void);
void send_UART(unsigned char i);
void UART_Interrupt_Receive(void);
void delay(unsigned char n);
void initADC(void);
void print_uint(unsigned int num);
void Long_delay();
void main()
{
Long_delay();//防止pc运行串口驱动时,与本程序自行向pc发送数据产生冲突,从而产生的混乱
Led=0;
serial_port_initial();
initADC();
AUXR=0x50; //T1定时器不分频,1T的速度,设置EADCI中断允许
IE=0xa0; //设置EADC_SPI中断和EA总中断允许
while(1)
;
}
void serial_port_initial(void) // 使用独立波特率发生器作为波特率发生器
{
SCON=0x50;//8位可变波特率,无奇偶校验位
TMOD=0X21;
AUXR=0x40; //T1定时器不分频,1T的速度
TH1=RELOAD_COUNT;
TL1=RELOAD_COUNT;
//TR1=1;
EA=1; // 开总中断
}
void send_UART(unsigned char i)
{
ES=0; // 关串口中断
TI=0; // 清零串口发送完成中断请求标志
SBUF=i;
while(TI==0); // 等待发送完成
TI=0; // 清零串口发送完成中断请求标志
//ES=1; // 允许串口中断
}
void print_uint(unsigned int num)
{
unsigned char w5,w4,w3,w2,w1;
w5=num/10000;
w4=num%10000/1000;
w3=num%1000/100;
w2=num%100/10;
w1=num%10;
send_UART('0'+w5);
send_UART('0'+w4);
send_UART('0'+w3);
send_UART('0'+w2);
send_UART('0'+w1);
send_UART(' ');
}
void delay(unsigned char n)
{
unsigned char x;
while(n--)
{
x=100;
while(x--);
}
}
void initADC()
{
ch=0;
//P1=P1M0=P1M1=0xff; //P1口设置为开漏型,做AD
P1=P1M0=0xef;
P1M1=0x00; //P1.0/2/3口设置为高阻输入,做AD. P1.4作准双向口,做led指示灯
ADC_DATA=0;
//此句不对,不能用或。ADC_CONTR=ADC_POWER|ADC_SPEEDL|ADC_START|ch|0xef;
ADC_CONTR=0x88;//ADC_CONTR=ADC_POWER|ADC_SPEEDL|ADC_START|ch|0xef
delay(2);
}
void adc_isr() interrupt 5
{
unsigned int dat;
unsigned char a;
AUXR=0x40; //T1定时器不分频,1T的速度,设置EADCI中断禁止
a=ADC_LOW2;//如果是dat=ADC_DATA<<8+ADC_LOW2&0x03;就会出错!莫名其妙!(在看到这的时候,忽然觉得好像是先算的8+ADC_LOW2&0x03···)
a=a&0x03;
dat=ADC_DATA*4+a; //如果是dat=ADC_DATA<<2+a 。就他妈的乱窜,一直飚过1024!
TR1=1;//开启定时器1 ,开启串口
send_UART(ch+0x30);
send_UART(':');
print_uint(dat);
delay(2); //如果没有延时,串口就会混乱!
TR1=0;//关闭定时器1
ADC_CONTR=0x88; //开启下一次转换
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
AUXR=0x10; //设置EADCI中断允许
}
void Long_delay()
{
unsigned char i,j,k;
for(k=0;k<50;k++)
for(i=0;i<255;i++)
for(j=0;j<255;j++)
;
}
完整资料打包: