173 2438 5004
KEROS加密芯片——品牌直销 | 免费样品 | 技术支持
当前位置:网站首页 > 资讯中心 正文 资讯中心

单片机ad通道切换

htxw 2023-03-13 资讯中心 30 ℃

单片机AD转换

1,什么是AD转换?

A是模拟信号的意思,D是数字信号的意思,AD转换就是模数转换,顾名思义,就是把模拟信号转换成数字信号,例如把电压值转化为数字信号。

2,为什么要AD转换?

单片机(以及其他处理器)只能处理数字信号,当单片机想要获取电路上某一点的电压值时,就得用到AD转换了,如果你直接把单片机的引脚接到电路这个点上,单片机只知道这个点的电压是低电平还是高电平,又怎么能得到他的电压值呢?例如数字式的万用表,它测量电压时,先有一个AD转换电路,把电压值转换成一个数值,然后把这个值送个单片机(当然万用表里的用的处理芯片不是单片机),单片机经过计算处理后,再把这电压值显示到显示到屏幕上。

不过现在有一些比较强的单片机,其内部已经集成了AD转换器,不需要你再外接AD转换芯片。

3,8位16位的ad转换芯片是什么意思?

8位,16位就代表了AD转换芯片的转换分辨率,数字越大,分辨率越高,同时也反映了它的精度,数字越大,精度相对也越高。8位算是最低了,有些单片机里集成的AD转换器一般是10位的。12位和16位的芯片价格就比较贵了。

4,分辨率?

举个简单的例子,8位芯片只能转换最小到0.01V的电压,而12位的芯片却能转换最小到0.001V的电压,如果一个电压为3.359V,8位芯片转出来后的数值是3.35V,12位芯片转换出来后是3.359V,精度比8位就高一个档次了。(注:这里数值不是正确的数值,举例用,切勿实际使用)

5,采样?

采样是AD转换的速度性能指标,通俗的说就是每秒里能采样多少次,采样次数越高芯片性能越好。如果对采样不理解,也可以用另一种方式理解,就是一个AD转换芯把电压值转换成数字值这个过程所需要的时间,时间越短越好。

6,精度?

精度是AD芯片的一个重要参数,表示采集到的数据和真实值之间的相差的程度。例如单片机转换出来的结果是0.3V,而实际可能是0.31V,这样就相差了0.01V。这种误差是不可避免无法消除的。这和在第3点中提到的位数有关,位数越高,这样的误差越小。

7,这些知识点在“数字电路基础”一书中有详细解释,说明你数字电路没学好,自己好好加油了。

pic单片机多路ad转换

我恰好做过一个PIC 4通道A/D,您先看看我的程序 有问题留言

#include pic.h //调用头文件,可以去PICC软件下去查找PIC16F873A单片机的头文件

#include stdio.h //调用头文件

#include math.h //调用头文件

__CONFIG(XTPROTECTWDTENPWRTEN); //定义配置字,晶振类型:XT,打开开门狗,代码保护

unsigned char count,count1,tunnel,t1s; //0.1s计时,1s计时,通道号,1s时间到标志

unsigned int result[4],s[4]; //转换电压结果、转换时间结果

unsigned char f[4]; //输入端口状态存储表

union{

struct{

unsigned b0:1; //通道1有输入标志

unsigned b1:1; //通道2有输入标志

unsigned b2:1; //通道3有输入标志

unsigned b3:1; //通道4有输入标志

unsigned b4:1; //通道1需要AD采样标志

unsigned b5:1; //通道2需要AD采样标志

unsigned b6:1; //通道3需要AD采样标志

unsigned b7:1; //通道4需要AD采样标志

}one;

unsigned char allbits;

}myflag; //共占一个字节的数据寄存器存储空间的标志位

#define b0 myflag.one.b0 //定义标志b0

#define b1 myflag.one.b1 //定义标志b1

#define b2 myflag.one.b2 //定义标志b2

#define b3 myflag.one.b3 //定义标志b3

#define b4 myflag.one.b4 //定义标志b4

#define b5 myflag.one.b5 //定义标志b5

#define b6 myflag.one.b6 //定义标志b6

#define b7 myflag.one.b7 //定义标志b7

#define in1 RB4 //定义1通道输入口为RB4端口

#define in2 RB5 //定义2通道输入口为RB5端口

#define in3 RB6 //定义3通道输入口为RB6端口

#define in4 RB7 //定义4通道输入口为RB7端口

#define out1 RC0 //定义1通道输出口为RC0端口

#define out2 RC1 //定义2通道输出口为RC1端口

#define out3 RC2 //定义3通道输出口为RC2端口

#define out4 RC3 //定义4通道输出口为RC3端口

//---------------------------------------

//名称: 定时器T0中断初始化函数

//-----------------------------------------

void T0init(void)

{

T0CS=0; //T0工作在定时器方式

PSA=0; //分频器给TMR0

PS0=1; //1:16分频

PS1=1;

PS2=0;

T0IF=0; //清零T0中断标志

T0IE=1; //清除T0中断使能

}

//---------------------------------------

//名称:RB口引脚电平变化中断初始化函数

//-----------------------------------------

void RBinit(void)

{

RBPU=1; //内部弱上拉禁止

RBIF=0; //中断标志清零

RBIE=1; //中断使能

PORTB=PORTB; //锁存旧值,为下次变化做准备

}

//---------------------------------------

//名称:RA口引脚A/D初始化函数

//-----------------------------------------

void ADinit(void)

{

ADCON1=0x00; //设置RA口所有为模拟输入,采取左对齐方式存放结果

ADCON0=0b11000001; //AD采样时钟为内部RC,默认第一次通道为RA0,启用转换模块

ADIE=0; //关闭中断使能禁止

}

//---------------------------------------

//名称: 主初始化函数

//-----------------------------------------

void init(void)

{

unsigned char i;

TRISA=0b00101111; //初始化AN0-AN5为输入

TRISC=0x00; //初始化C口为输出

TRISB=0xFF; //初始化RB0-RB7为输入

PORTC=0b00000000; //初始化输出

count=0; //初始化T0计数器

count1=0; //初始化T0计数器

tunnel=1; //初始化通道号为1

myflag.allbits=0x00; //初始化标志位

for(i=0;i4;i++) //初始化延时量和输入端口状态

{s[i]=30;

f[i]=0;}

}

//---------------------------------------

//-----------------------------------------

//名称: 中断服务子函数

//-----------------------------------------

void interrupt ISR(void)

{

//全局中断屏蔽

if(RBIFRBIE) //RB边沿中断类型判别

{

PORTB=PORTB;

RBIF=0;

if(in1) //判断1通道状态

b0=1;

else

b0=0;

if(in2) //判断2通道状态

b1=1;

else

b1=0;

if(in3) //判断3通道状态

b2=1;

else

b2=0;

if(in4) //判断4通道状态

b3=1;

else

b3=0;

} //RB_int服务子程序1

if(T0IFT0IE) //定时器T0中断类型判别

{

TMR0=TMR0+8; //发生一次的时间为250*16=4ms

T0IF=0;

count+=1;

if(count==25) //计数基数25*16*250=0.1s

{

count=0;

count1+=1;

if(count1==5) //计数基数0.1s*5=0.5s

{

count1=0;

t1s=1; //1s时间到标志

}

}

} //Tmr0_int服务子程序3

//全局中断使能

}

//-----------------------------------------

//名称:delay延时

//-----------------------------------------

void delay()

{

unsigned int i;

for(i=0;i10;i++);//采样延时160us

}

//-----------------------------------------

//-----------------------------------------

//名称:A/D转换选择子程序

//-----------------------------------------

void ADconvert(void)

{

switch(tunnel) //AD通道选择

{

case 1: //1通道AD采样转换

ADCON0=0b11000001; //设置1通道

delay(); //采样延时

#asm

clrf _STATUS ;

bsf _ADCON0,2 ;

btfsc _ADCON0,2 ;

goto $-1 ;

#endasm //结束采样

result[0]=ADRESH; //把结果保存

s[0]=result[0]*1208; //把结果转化为时间

if(s[0]2) //限制最小值1s

s[0]=2;

else if(s[0]120)

s[0]=120; //限制最大值60s

break; //跳出

case(2): //2通道AD采样转换

ADCON0=0b11001001; //设置2通道

delay(); //采样延时

#asm

clrf _STATUS ;

bsf _ADCON0,2 ;

btfsc _ADCON0,2 ;

goto $-1 ;

#endasm //结束采样

{result[1]=ADRESH;} //把结果保存

s[1]=result[1]*1208; //把结果转化为时间

if(s[1]2) //限制最小值1s

s[1]=2;

else if(s[1]120)

s[1]=120; //限制最大值60s

break; //跳出

case(3): //3通道AD采样转换

ADCON0=0b11010001; //设置3通道

delay();

#asm

clrf _STATUS ;

bsf _ADCON0,2 ;

btfsc _ADCON0,2 ;

goto $-1 ;

#endasm //结束采样

{result[2]=ADRESH;} //把结果保存

s[2]=result[2]*1208; //把结果转化为时间

if(s[2]2) //限制最小值1s

s[2]=2;

else if(s[2]120)

s[2]=120; //限制最大值60s

break; //跳出

case(4): //4通道AD采样转换

ADCON0=0b11011001; //设置4通道

delay(); //采样延时

#asm

clrf _STATUS ;

bsf _ADCON0,2 ;

btfsc _ADCON0,2 ;

goto $-1 ;

#endasm //结束采样

{result[3]=ADRESH;} //把结果保存

s[3]=result[3]*1208; //把结果转化为时间

if(s[3]2) //限制最小值1s

s[3]=2;

else if(s[3]120)

s[3]=120; //限制最大值60s

break; //跳出

default:break; //出错跳出

}

}

//---------------------------------------

//名称:deal通道处理

//-----------------------------------------

void deal(void)

{

unsigned char i;

if(t1s) //判断0.5秒时间是否到

{

asm("nop");

t1s=0; //0.5秒时间标志清零,等待下0.5秒

if(b0) //是第1通道吗

{

if(b4) //是第1通道有变化后的采样吗

{tunnel=1; //赋值AD通道号

ADconvert(); //开始AD转换

b4=0;} //没变化不再采样

if(!(s[0]--)) //延时计时开始

out1=1;} //继电器开始动作

else out1=0;

if(b1) //是第2通道吗

{

if(b5) //是第2通道有变化后的采样吗

{tunnel=2; //赋值AD通道号

ADconvert(); //开始AD转换

b5=0;} //没变化不再采样

if(!(s[1]--)) //延时计时开始

out2=1;} //继电器开始动作

else out2=0;

asm("clrwdt");

if(b2) //是第3通道吗

{

if(b6) //是第3通道有变化后的采样吗

{tunnel=3; //赋值AD通道号

ADconvert(); //开始AD转换

b6=0;} //没变化不再采样

if(!(s[2]--)) //延时计时开始

out3=1;} //继电器开始动作

else out3=0;

if(b3) //是第4通道吗

{

if(b7) //是第4通道有变化后的采样吗

{tunnel=4; //赋值AD通道号

ADconvert(); //开始AD转换

b7=0;} //没变化不再采样

if(!(s[3]--)) //延时计时开始

out4=1;} //继电器开始动作

else out4=0;

}

asm("nop"); //1秒时间没到继续检测

}

//-----------------------------------------

//名称:主函数

//-----------------------------------------

void main()

{

init(); //全局初始化

T0init(); //T0初始化

ADinit(); //A/D初始化

RBinit(); //RB初始化

asm("nop"); //稳定状态

asm("nop");

delay();

delay(); //耗时0.7ms

//-----------------------------------------

{ //开机初始化采样AD

tunnel=1;

ADconvert();

tunnel=2;

ADconvert();

tunnel=3;

ADconvert();

tunnel=4;

ADconvert();

} //开机1次AD,到此耗时2.4ms,这个时间前不要有触发

if(in1) //开机一次状态判断

{b0=1;

f[0]=in1;} //存储开机时1通道状态

if(in2)

{b1=1;

f[1]=in2;} //存储开机时2通道状态

if(in3)

{b2=1;

f[2]=in3;} //存储开机时3通道状态

if(in4)

{ b3=1;

f[3]=in4;} //存储开机时4通道状态

//-----------------------------------------

ei(); //打开全局中断

//-----------------------------------------

while(1) //主循环

{

asm("clrwdt"); //清看门狗

if(b0) //判断1通道状态

{

if(f[0]!=in1)

{f[0]=in1; //存储1通道状态

b4=1;} //1通道是否进行AD标志

} //设定1通道有效标志

else

{

b4=0;

f[0]=in1;} //设定1通道无效标志

if(b1) //判断2通道状态

{

if(f[1]!=in2)

{f[1]=in2; //存储2通道状态

b5=1;} //2通道是否进行AD标志

} //设定2通道有效标志

else

{

b5=0;

f[1]=in2;} //设定2通道无效标志

if(b2) //判断3通道状态

{

if(f[2]!=in3)

{f[2]=in3; //存储3通道状态

b6=1;} //3通道是否进行AD标志

} //设定3通道有效标志

else

{

b6=0;

f[2]=in3;} //设定3通道无效标志

if(b3) //判断4通道状态

{

if(f[3]!=in4)

{f[3]=in4; //存储4通道状态

b7=1;} //4通道是否进行AD标志

} //设定4通道有效标志

else

{

b7=0;

f[3]=in4;} //设定4通道无效标志

deal(); //最大循环时间不超过4ms,看门狗典型值18ms

asm("nop"); //中断检测

}

}

//---------------------------------------

为什么51单片机不能同时多路ad转换?如果只有一个ad芯片,那么要实现多路转换该怎么做?

虽然只有一个芯片,但多数AD芯片都 有多个输入通道(包括单片机内部的AD模块),且AD转换速度较高,因此可以分时复用,对于一些变化缓慢的信号,分时转换结果可以看作是”同时“转换得到的.

对于只有一个输入通道的AD芯片我们也可以用CD4511等电子开关来选择切换不同的信号

如何使用STM8S单片机的多通道AD转换

我给你个例程,我这是两个通道,一个是采集音频,然后彩灯随音乐节奏闪烁,同时采集电池电量。

void AD2_Config(void)

{

/* Init GPIO for ADC2 */

GPIO_Init(GPIOB, GPIO_PIN_6, GPIO_MODE_IN_FL_NO_IT);

/* De-Init ADC peripheral*/

ADC1_DeInit();

ADC1_ClearITPendingBit(ADC1_IT_EOC);

/* Init ADC1 peripheral */

ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_6, ADC1_PRESSEL_FCPU_D18, \

ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL6,\

DISABLE);

/* Enable EOC interrupt */

//if(autoFm == 1)

ADC1_ITConfig(ADC1_IT_EOCIE,DISABLE);

//else

// ADC1_ITConfig(ADC1_IT_EOCIE,ENABLE);

/* Enable general interrupts */

/*Start Conversion */

ADC1_StartConversion();

}

void AD_Config(void)

{

/* Init GPIO for ADC2 */

GPIO_Init(GPIOB, GPIO_PIN_7, GPIO_MODE_IN_FL_NO_IT);

// GPIOD-ODR = 0x8f;

/* De-Init ADC peripheral*/

ADC1_DeInit();

ADC1_ClearITPendingBit(ADC1_IT_EOC);

/* Init ADC1 peripheral */

ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_7, ADC1_PRESSEL_FCPU_D18, \

ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL7,\

DISABLE);

/* Enable EOC interrupt */

// if(autoFm == 1)

// ADC1_ITConfig(ADC1_IT_EOCIE,DISABLE);

//else

ADC1_ITConfig(ADC1_IT_EOCIE,ENABLE);

/*Start Conversion */

ADC1_StartConversion();

}

main()

{

TIM2_Config();

TIM4_Config();

AD2_Config();

TIM1_Config();

enableInterrupts();

while(1)

{

if(ADChange = 1)//这是个延时,多久进一次

{

AD2_Config();

while(RESET == ADC1_GetFlagStatus(ADC1_FLAG_EOC));

VoicADLeve = ADC1_GetConversionValue();

AD_Config();

ADChange = 0;

ADChange = 0;

}

}

}

在ADC中断里面

INTERRUPT_HANDLER(ADC2_IRQHandler, 22)

{

ADC1_ClearITPendingBit(ADC2_IT_EOC);

}

INTERRUPT_HANDLER(ADC1_IRQHandler, 22)

{

uint16_t temp;

temp = ADC1_GetConversionValue();//这是采集音频

if(temp min_ad)

{

min_ad = temp;

}

if(temp max_ad)

{

max_ad= temp;

}

ADC1_ClearITPendingBit(ADC1_IT_EOC);

}

这程序我只给了你ADC的部分

谁做过单片机和AD转换,多通道的AD,在两个通道该怎么切换并且用数码管显示的?

单片机at89s51和ADC0809

1)汇编源程序:

CH EQU 30H

DPCNT EQU 31H

DPBUF EQU 33H

GDATA EQU 32H

ST BIT P3.0

OE BIT P3.1

EOC BIT P3.2

ORG 00H

LJMP START

ORG 0BH

LJMP T0X

ORG 30H

START: MOV CH,#0BCH

MOV DPCNT,#00H

MOV R1,#DPCNT

MOV R7,#5

MOV A,#10

MOV R0,#DPBUF

LOP: MOV @R0,A

INC R0

DJNZ R7,LOP

MOV @R0,#00H

INC R0

MOV @R0,#00H

INC R0

MOV @R0,#00H

MOV TMOD,#01H

MOV TH0,#(65536-4000)/256

MOV TL0,#(65536-4000) MOD 256

SETB TR0

SETB ET0

SETB EA

WT: CLR ST

SETB ST

CLR ST

WAIT: JNB EOC,WAIT

SETB OE

MOV GDATA,P0

CLR OE

MOV A,GDATA

MOV B,#100

DIV AB

MOV 33H,A

MOV A,B

MOV B,#10

DIV AB

MOV 34H,A

MOV 35H,B

SJMP WT

T0X: NOP

MOV TH0,#(65536-4000)/256

MOV TL0,#(65536-4000) MOD 256

MOV DPTR,#DPCD

MOV A,DPCNT

ADD A,#DPBUF

MOV R0,A

MOV A,@R0

MOVC A,@A+DPTR

MOV P1,A

MOV DPTR,#DPBT

MOV A,DPCNT

MOVC A,@A+DPTR

MOV P2,A

INC DPCNT

MOV A,DPCNT

CJNE A,#8,NEXT

MOV DPCNT,#00H

NEXT: RETI

DPCD: DB 3FH,06H,5BH,4FH,66H

DB 6DH,7DH,07H,7FH,6FH,00H

DPBT: DB 0FEH,0FDH,0FBH,0F7H

DB 0EFH,0DFH,0BFH,07FH

END

2)C语言源程序

#include

unsigned char code dispbitcode[]={0xfe,0xfd,0xfb,0xf7,

 0xef,0xdf,0xbf,0x7f};

unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f,0x66,

0x6d,0x7d,0x07,0x7f,0x6f,0x00};

unsigned char dispbuf[8]={10,10,10,10,10,0,0,0};

unsigned char dispcount;

sbit ST="P3"^0;

sbit OE="P3"^1;

sbit EOC="P3"^2;

unsigned char channel="0xbc";//IN3

unsigned char getdata;

void main(void)

{

TMOD=0x01;

TH0=(65536-4000)/256;

TL0=(65536-4000)%256;

TR0=1;

ET0=1;

EA=1;

P3=channel;

while(1)

{

ST=0;

ST=1;

ST=0;

while(EOC==0);

OE=1;//片选

getdata=P0;

OE=0;

dispbuf[2]=getdata/100;

getdata=getdata%10;

dispbuf[1]=getdata/10;

dispbuf[0]=getdata%10;

}

}

void t0(void) interrupt 1 using 0

{

TH0=(65536-4000)/256;

TL0=(65536-4000)%256;

P1=dispcode[dispbuf[dispcount]];

P2=dispbitcode[dispcount];

dispcount++;

if(dispcount==8)

{

dispcount=0;

}

}

单片机ad通道切换的介绍就聊到这里吧,感谢您花时间阅读,谢谢。

本文标签:单片机ad通道切换

<