
考虑的问题。
1 可以使用运放做加法电路,和一个给定参考电压相加,在负极性的峰值时,能保证运放输出>=0V,这个可以通过调整给定参考来实现
2 记得运放一定用双电源供电,或者轨对轨运放单电源也行。
3 考虑,信号的动态范围,如果信号的最大峰峰值超过MCU的参考电压,就会出现消顶,而导致采样失真。所以在加法电路之前,最后加一级运放反向放大/缩小的处理,可以调整信号的最大峰峰值《= MCU的参考电压。放大/缩小倍数通过软件处理还原。
不知能否帮到你!!!
//1602 四线制驱动程序,根据需要自己改端口定义和延时
#define LINE1 0
#define LINE2 1
#define LINE1_HEAD 0x80
#define LINE2_HEAD 0xC0
#define CLEARSCREEN LCD_en_com(0x01);LCD_delay(30)
//
//change this part at different board
sbit DB7=P2^7;
sbit DB6=P2^6;
sbit DB5=P2^5;
sbit DB4=P2^4;
sbit LCD1602_RS=P2^1; //data command select 1 data 0 command pin 4
sbit LCD1602_RW=P2^2; //read write select 1 read 0 write pin 5
sbit LCD1602_EN=P2^3; //LCD enable signal pin 6
//
void LCD_delay(unsigned int n)
{
unsigned int i=0,j=0;
for (i=n;i>0;i--)
for (j=0;j<12;j++);
}
void LCD_en_com(unsigned char command)
{
DB7=(command>>7)%2;
DB6=(command>>6)%2;
DB5=(command>>5)%2;
DB4=(command>>4)%2;
LCD1602_RS = 0; //RS 0
LCD1602_RW = 0; //RW 0
LCD1602_EN = 1; //EN --\|/__ Write command
LCD_delay(2);
LCD1602_EN = 0;
DB7=(command>>3)%2;
DB6=(command>>2)%2;
DB5=(command>>1)%2;
DB4=(command>>0)%2;
LCD1602_RS = 0; //RS 0
LCD1602_RW = 0; //RW 0
LCD1602_EN = 1; //EN --\|/__ Write command
LCD_delay(2);
LCD1602_EN = 0;
}
void LCD_en_dat(unsigned char command)
{
DB7=(command>>7)%2;
DB6=(command>>6)%2;
DB5=(command>>5)%2;
DB4=(command>>4)%2;
LCD1602_RS = 1; //RS 1
LCD1602_RW = 0; //RW 0
LCD1602_EN = 1; //EN --\|/__ Write data
LCD_delay(2);
LCD1602_EN = 0;
DB7=(command>>3)%2;
DB6=(command>>2)%2;
DB5=(command>>1)%2;
DB4=(command>>0)%2;
LCD1602_RS = 1; //RS 1
LCD1602_RW = 0; //RW 0
LCD1602_EN = 1; //EN --\|/__ Write data
LCD_delay(2);
LCD1602_EN = 0;
}
void LCD_set_xy(unsigned char x,unsigned char y)
{
unsigned char address;
if(y == LINE1)
address = LINE1_HEAD + x;
else
address = LINE2_HEAD + x;
LCD_delay(10);
LCD_en_com(address);
}
void LCD_write_string(unsigned char x,unsigned char y,unsigned char s)
{
LCD_set_xy(x,y);
while(s)
{
LCD_en_dat(s);
s++;
}
}
//
void InitTimer0(void)//200us
{
TMOD = 0x01;
TH0 = 0x0FE;
TL0 = 0x70;
EA = 1;
ET0 = 1;
TR0 = 1;
}
unsigned char LCD_ContCount=0;
sbit LCDCONT=P2^0;
void Timer0Interrupt(void) interrupt 1
{
TH0 = 0x0FE;
TL0 = 0x70;
if(LCD_ContCount<LCD_CONTRAST){LCDCONT=0;}
else{LCDCONT=1;}
LCD_ContCount++;
if(LCD_ContCount==100){LCD_ContCount=0;}
}
//
void LCD_init(void)
{
LCD_delay(50);
LCD_en_com(0x33);//原来1602初始化成4位数据线之前必需先初始化成8位(此时命令发送方式是8位格式,但数据线只需接4位)
LCD_delay(10);
LCD_en_com(0x32);//然后再改到4位线宽,这样初始化才稳定
LCD_delay(10);
LCD_en_com(0x28);//四线模式设置
LCD_delay(10);
LCD_en_com(0x0c);//显示开--对应开关显示控制指令
LCD_delay(10);
CLEARSCREEN;
InitTimer0();
}
//
至于AD,用片上自带的AD就行,没有具体的电路,只能帮你这些了。
另:楼上说用ADC0834的,STC12C5A60S2已经有AD了啊
//定义与ADC有关的特殊功能寄存器
sfr ADC_CONTR =0xC5;
sfr ADC_DATA =0xC6;
sfr ADC_LOW2 =0xBE;
sfr P1M0 =0x91;
sfr P1M1 =0x92;
sbit p20 =P2^0;
void STC90CxxAD_delay(int timer) //延时函数
{
while(timer--);
}
int Ad_Change(char channel) //AD转换
{
int AD_Result_Temp = 0 ;
P1 = 0xff; //将P1口置高,为A/D转换作准备
ADC_CONTR = ADC_CONTR|0x80; //1000,0000打开A/D转换电源
P1M0 = 0x03; //0000,0011用于A/D转换的P1x口,先设为开漏
P1M1 = 0x03; //0000,0011P10--P11先设为开漏。断开内部上拉电阻
STC90CxxAD_delay(20); //20
ADC_CONTR = ADC_CONTR&0xE0; //1110,0000 清ADC_FLAG,ADC_START位和低3位
ADC_CONTR = ADC_CONTR|(channel); //设置当前通道号
STC90CxxAD_delay(1); //延时使输入电压达到稳定
ADC_DATA = 0; //清A/D转换结果寄存器
ADC_LOW2 = 0;
ADC_CONTR = ADC_CONTR|0x08; //0000,1000ADCS = 1,启动转换
do { ; }
while((ADC_CONTR & 0x10)==0); //0001,0000等待A/D转换结束
ADC_CONTR = ADC_CONTR&0xE7; //1110,0111清ADC_FLAG位,停止A/D转换
AD_Result_Temp = ((AD_Result_Temp|ADC_DATA)<<2)|(ADC_LOW2&0x03);
//保存返回AD转换的 结果
STC90CxxAD_delay(1); //
return AD_Result_Temp;
}
已调试通过,望对你有用
/ ADC Test
电压 P00电压采集 可以测试0-5V的外部电压值 用1602显示
//////////////////////// /
/ LCD1602
LCD1602显示 rs P3^5 rw P3^6 ep P3^7 P2口 为数据输出口
///////////////////////
STC12 ADC电压采集测试程序 /
#include <reg52H>
#include "intrinsh"
#define uchar unsigned char
#define uint unsigned int
uchar Vo; //A/D转换后换算的电压值
int i,e;
/Define ADC operation const for ADC_CONTR/
#define ADC_POWER 0x80 //ADC power control bit
#define ADC_FLAG 0x10 //ADC complete flag 模数转换结束标志位
#define ADC_START 0x08 //ADC start control bit 模数转换启动控制位
//转换速度控制位SPEED0和SPEED1,共四种状态,对应四种转换速度
#define ADC_SPEEDLL 0x00 //540 clocks
#define ADC_SPEEDL 0x20 //360 clocks
#define ADC_SPEEDH 0x40 //180 clocks
#define ADC_SPEEDHH 0x60 //90 clocks
sbit rw=P3^6; //1602 IO口定义 这里用的数据口是P2口
sbit rs=P3^5;
sbit ep=P3^7;
uchar code asc[] = "0123456789";
unsigned char code d[] = {"ADC Test"};
unsigned char code a[] ={ //汉字
0x04,0x1f,0x15,0x1f,0x15,0x1f,0x05,0x07, //电
0x0f,0x08,0,0,0x0f,0,0x13,0x0f, //压
};
/ 延时函数 /
void delay(unsigned int a)
{
while(a--);
}
/----------------------------
Get ADC result
----------------------------/
uchar GetADCResult(uchar ch) //这里如有不懂 请仔细看资料
{
P1ASF = 0x01; //选择P1口的哪一口 这里的口和ch要对应才能达到选择该口
ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;//0x00|0x00|ch|0x08:选择A/D输入通道,开始A/D转换
// 这么用语句的主要原因就是不能位寻址
// 通道选择在后3位所以直接用一个整数表示ch
//例如ch=6 那么对应的后三位就是110
_nop_(); //Must wait before inquiry ,
_nop_(); //设置ADC_CONTR寄存器后需加4个CPU时钟周期的延时,才能保证值被写入ADC_CONTR寄存器
_nop_();
_nop_();
while (!(ADC_CONTR & ADC_FLAG));//Wait complete flag
ADC_CONTR &= ~ADC_FLAG; //Close ADC 将标志位清零等待下次硬件置1
//也可以写成 ADC_CONTR= ADC_CONTR & ( ~ADC_FLAG)
Vo=ADC_RES510/256; //Return ADC result(为显示整数,这里将电压值扩大了十倍)
//5/256 因为是8位 把5V分成256份 ADC_RES为采集的份数
//ADC_RES(5/256) 为采集的电压值 然后扩大10倍便于计算
return Vo;
}
//
//
/ 1602 /
bit lcd_busy() //查忙 这部很重要 否则有的显示容易出现乱码
{
bit result;
rs = 0;
rw = 1;
ep = 1;
delay(50);
result = (bit)(P2&0x80);
ep = 0;
return result; //返回值
}
void lcd_com(unsigned char com)// 地址
{
while(lcd_busy());
rs=0;
ep=0;
rw=0;
P2=com;
delay(50);
ep=1;
delay(50);
ep=0;
}
void lcd_date(unsigned char date)//采集输出数据
{
while(lcd_busy());
rs=1; //1是些数据 0是写指令
rw=0; // 1是读 0是写
ep=0; //E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令
P2=date;
delay(5);
ep=1;
delay(5);
ep=0;
}
void lcd_pos(unsigned char pos)
{
lcd_com(pos|0x80); //数据指针=80+地址变量
}
void writetab() // 写 汉字函数
{
unsigned char m;
lcd_com(0x40); //写CGRAM 此处是指令
for (m = 0; m<16; m++)
lcd_date(a[m]);
}
void init()//1602初始化
{
lcd_com(0x38);
delay(50);
lcd_com(0x38);
delay(50);
lcd_com(0x38);
delay(50);
lcd_com(0x0c);
delay(50);
lcd_com(0x06);
delay(50);
lcd_com(0x01);
delay(2000);
writetab() ; // 汉字初始化
}
//
//
//
void hanzi() //汉字显示
{
lcd_pos(0x40); //电压
lcd_date(0x00);
lcd_pos(0x40+1);
lcd_date(0x01);
}
//
void main(void)
{
TMOD=0x01; //选择定时器T0 在工作方式1上 即16位定时器
TH0=(65536-50000)/256; //11592M晶振的一个机器周期接近1us 这里5W就是005s
TL0=(65536-50000)%256;
EA=1; //开启总中断
ET0=1; //开启定时器T0
TR0=1; // 启动定时器 使其开始计算
init(); //1602初始化
lcd_pos(0x00); //显示字母
i=0;
while(d[i]!='\0')
{
lcd_date(d[i]);
i++;
}
hanzi(); //显示汉字
delay(300);
while(1)
{
lcd_pos(0x42);
lcd_date(':');
lcd_date(asc[Vo/10]);
lcd_date('');
lcd_date(asc[Vo%10]);
lcd_date('V');
}
}
void ADCt0() interrupt 1
{
TH0 = (65536-50000)/256;
TL0 = (65536-50000)%256;
e++;
if(e==20)
{ e=0;
GetADCResult(0);
}
}
void adc_isr() interrupt 5 using 1
{
ch++;
}
请教您是如何测试判断,程序根本就没有进入过AD的中断处理程序
以上就是关于STC单片机做AD转换时双极性信号程序是怎么处理的编程思路是怎么样的啊全部的内容,包括:STC单片机做AD转换时双极性信号程序是怎么处理的编程思路是怎么样的啊、STC12C5A60S2 AD转换C语言程序,转换结果在1602液晶上显示。、请给一个STC 90C58AD 的单片机AD转换的C程序。谢谢。 有的话发到我的邮箱里lylhe@163.com 谢谢!等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)