模块分类:AD转换模块、按键处理模块、显示模块。
AD转换模块:这部分电路要自己设计,总之就是将电压输入AD转换芯片输出数字信号。输出端接单片机IO(如果)口。将得到的电压值加入算法得到所需要的电阻值或电容值。
按键处理模块:书上基本都有。
显示模块:这部分就是LED动态显示的问题了,随便一本单片机书里面都有例题。
AD转换不是一条指令就可以完成的,它要先经过端口设置,AD设置等过程后才能准备进入AD转换,下例是从北航的<PIC16单片机C程序设计与PROTEUS仿真>一书中得到的启发编制的程序,希望对你能有帮助建议你看一下这本书,对初学和想进一步提高在PIC单片机应用编程等会有用的
附图是对应程序的,在仿真时调整电位器可以看到AD结果的变化,并通过计算器可以验证程序的正确性
//ADl转换示例,可以改变输入电压、AD通道、结果对齐方式等,看其变化
#include <pich>
__CONFIG(0x3F39); //配置位设置
void main(void)
{ char i,X,Y;
TRISA=0xFF; //将所有的A口设置为输入
TRISE=0x03; //将所有的E口设置为输入
TRISD=0; //C口与D口全为输出
TRISC=0;
ADCON1=0b10000000; //设置AD结果对齐方式、AD时钟选择(与ADCON0的位7,6一起),AD端口设置等
ADCON0=0b01011001; //AD时钟选择(与ADCON1的位6一起),通道选择,AD模块使能
while(1)
{ NOP();
for (i=0;i<3;i++) //延时时间大约20us
NOP();
ADGO=1; //开始AD
while(ADGO==1); //等待AD转换完成
ADIF=0;
X=ADRESH; //读取AD结果高字节至C口
PORTC=X;
Y=ADRESL; //读取AD结果低字节至D口
PORTD=Y;
};
}
void adc_isr() interrupt 5 using 1
{
ch++;
}
请教您是如何测试判断,程序根本就没有进入过AD的中断处理程序
#include <reg52h>#include <intrinsh>#define uchar unsigned char#define uint unsigned intsbit DS=P3^3; //定义DS18B20接口int temp; uchar flag1; void display(unsigned char lp,unsigned char lc);//数字的显示函数;lp为指向数组的地址,lc为显示的个数void delay();//延时子函数,5个空指令code unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0x40,0x39,0x00};//共阴数码管显示数的组成是 "0-9""0-9有小数点的" "-" "C" "空 表"unsigned char l_tmpdate[8]={0,0,10,0,0,0,0,0};//定义数组变量,并赋值1,2,3,4,5,6,7,8,就是本程序显示的八个数int tmp(void);void tmpchange(void);void tmpwritebyte(uchar dat);uchar tmpread(void);bit tmpreadbit(void);void dsreset(void);void delayb(uint count);void main() //主函数{uchar i;int l_tmp; while(1) { tmpchange(); //温度转换 l_tmp=tmp(); //读取温度值 if(l_tmp<0) l_tmpdate[0]=20; //判断温度为负温度,前面加"-" else { l_tmpdate[0]=l_tmp/1000; //显示百位,这里用1000,是因为我们之前乖以10了 if(l_tmpdate[0]==0) l_tmpdate[0]=22;//判断温度为正温度且没有上百,前面不显示,查表第12是空 }l_tmp=l_tmp%1000;l_tmpdate[1]=l_tmp/100;//获取十位l_tmp=l_tmp%100;l_tmpdate[2]=l_tmp/10;//获取个位再l_tmpdate[2]+=10;//加入小数点,查表可得出有小数点的排在后10位,所以加10l_tmpdate[3]=l_tmp%10;//获取小数第一位l_tmpdate[4]=21;for(i=0;i<10;i++){ //循环输出10次,提高亮度display(l_tmpdate,5); } }}void display(unsigned char lp,unsigned char lc)//显示{ unsigned char i; //定义变量 P2=0; //端口2为输出 P1=P1&0xF8; //将P1口的前3位输出0,对应138译门输入脚,全0为第一位数码管 for(i=0;i<lc;i++){ //循环显示 P2=table[lp[i]]; //查表法得到要显示数字的数码段 delay(); //延时5个空指令 if(i==7) //检测显示完8位否,完成直接退出,不让P1口再加1,否则进位影响到第四位数据 break; P2=0; //清0端口,准备显示下位 P1++; //下一位数码管 }}void delay(void) //空5个指令{_nop_();_nop_();_nop_();_nop_();_nop_();}void delayb(uint count) //delay{ uint i; while(count) { i=200; while(i>0) i--; count--; }答案补充
}void dsreset(void)//DS18B20初始化{ uint i; DS=0; i=103; while(i>0)i--; DS=1; i=4; while(i>0)i--;}bit tmpreadbit(void) // 读一位{ uint i; bit dat; DS=0;i++; //小延时一下 DS=1;i++;i++; dat=DS; i=8;while(i>0)i--; return (dat);}uchar tmpread(void) //读一个字节{ uchar i,j,dat; dat=0; for(i=1;i<=8;i++) { j=tmpreadbit(); dat=(j<<7)|(dat>>1); } return(dat); } 答案补充
void tmpwritebyte(uchar dat) { uint i; uchar j; bit testb; for(j=1;j<=8;j++) { testb=dat&0x01; dat=dat>>1; if(testb) { DS=0; i++;i++; DS=1; i=8;while(i>0)i--; } else { DS=0; i=8;while(i>0)i--; DS=1; i++;i++; } }}void tmpchange(void){ dsreset(); delayb(1); tmpwritebyte(0xcc); tmpwritebyte(0x44); }答案补充
int tmp() //获得温度{ float tt; uchar a,b; dsreset(); delayb(1); tmpwritebyte(0xcc); tmpwritebyte(0xbe); //发送读取数据命令 a=tmpread(); //连续读两个字节数据 b=tmpread(); temp=b; temp<<=8; temp=temp|a; //两字节合成一个整型变量。 tt=temp00625; //得到真实十进制温度值,因为DS18B20//可以精确到00625度,所以读回数据的最低位代表的是//00625度。 temp=tt10+05; //放大十倍,这样做的目的将小数点后第一位//也转换为可显示数字,同时进行一个四舍五入 *** 作。 return temp; //返回温度值}答案补充
void readrom() //read the serial 读取温度传感器的序列号{ //本程序中没有用到此函数 uchar sn1,sn2; dsreset(); delayb(1); tmpwritebyte(0x33); sn1=tmpread(); sn2=tmpread();}void delay10ms() { uchar a,b; for(a=10;a>0;a--) for(b=60;b>0;b--);}哇!好累啊。。。这个可以用。。。用那个口自己看看就懂了,如果要汇编语言的去看:>
//定义与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;
}
已调试通过,望对你有用
你的:
SBUF = P1; //读数据并发送
问题稍稍复杂了一点,分解一下,改为:
P2 = P1; //读数据当场显示,观察数据是否正确
SBUF = 100; //发送一个自定义的数据,观察对方接收的情况
delayms(200);//多延时一会,等待发送完毕
试试看,找出毛病出在何处。
以上就是关于跪求一个A/D转换的C语言程序,有程序说明。全部的内容,包括:跪求一个A/D转换的C语言程序,有程序说明。、pic系列单片机用c语言编程时,让他执行A/D转换的指令是什么、STC12C5A16S2单片机的AD转换功能,采用中断方式的C代码问题。等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)