求51单片机AD程序

求51单片机AD程序,第1张

如下程序是在 STC 官方网站 提供的。应该很有用。

////

//本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译

//假定测试芯片的工作频率为18.432MHz

#include "reg51.h"

#include "intrins.h"

#define FOSC18432000L

#define BAUD9600

typedef unsigned char BYTE

typedef unsigned int WORD

#define URMD0 //0:使用定时器2作为波特率发生器

//1:使用定时器1的模式0(16位自动重载模式)作为波特率发生器

//2:使用定时器1的模式2(8位自动重载模式)作为波特率发生器

sfr T2H = 0xd6 //定时器2高8位

sfr T2L = 0xd7 //定时器2低8位

sfr AUXR = 0x8e //辅助寄存器

sfr ADC_CONTR = 0xBC //ADC控制寄存器

sfr ADC_RES = 0xBD //ADC高8位结果

sfr ADC_LOW2= 0xBE //ADC低2位结果

sfr P1ASF = 0x9D //P1口第2功能控制寄存器

#define ADC_POWER 0x80//ADC电源控制位

#define ADC_FLAG0x10//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 InitADC()

void SendData(BYTE dat)

BYTE GetADCResult(BYTE ch)

void Delay(WORD n)

void ShowResult(BYTE ch)

void main()

{

InitUart()//初始化串口

InitADC() //初始化ADC

while (1)

{

ShowResult(0) //显示通道0

ShowResult(1) //显示通道1

ShowResult(2) //显示通道2

ShowResult(3) //显示通道3

ShowResult(4) //显示通道4

ShowResult(5) //显示通道5

ShowResult(6) //显示通道6

ShowResult(7) //显示通道7

}

}

/*----------------------------

发送ADC结果到PC

----------------------------*/

void ShowResult(BYTE ch)

{

SendData(ch) //显示通道号

SendData(GetADCResult(ch))//显示ADC高8位结果

//SendData(ADC_LOW2) //显示低2位结果

}

/*----------------------------

读取ADC结果

----------------------------*/

BYTE GetADCResult(BYTE ch)

{

ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START

_nop_() //等待4个NOP

_nop_()

_nop_()

_nop_()

while (!(ADC_CONTR &ADC_FLAG))//等待ADC转换完成

ADC_CONTR &= ~ADC_FLAG//Close ADC

return ADC_RES//返回ADC结果

}

/*----------------------------

初始化串口

----------------------------*/

void InitUart()

{

SCON = 0x5a //设置串口为8位可变波特率

#if URMD == 0

T2L = 0xd8//设置波特率重装值

T2H = 0xff//115200 bps(65536-18432000/4/115200)

AUXR = 0x14 //T2为1T模式, 并启动定时器2

AUXR |= 0x01 //选择定时器2为串口1的波特率发生器

#elif URMD == 1

AUXR = 0x40 //定时器1为1T模式

TMOD = 0x00 //定时器1为模式0(16位自动重载)

TL1 = 0xd8//设置波特率重装值

TH1 = 0xff//115200 bps(65536-18432000/4/115200)

TR1 = 1 //定时器1开始启动

#else

TMOD = 0x20 //设置定时器1为8位自动重装载模式

AUXR = 0x40 //定时器1为1T模式

TH1 = TL1 = 0xfb //115200 bps(256 - 18432000/32/115200)

TR1 = 1

#endif

}

/*----------------------------

初始化ADC

----------------------------*/

void InitADC()

{

P1ASF = 0xff //设置P1口为AD口

ADC_RES = 0 //清除结果寄存器

ADC_CONTR = ADC_POWER | ADC_SPEEDLL

Delay(2) //ADC上电并延时

}

/*----------------------------

发送串口数据

----------------------------*/

void SendData(BYTE dat)

{

while (!TI) //等待前一个数据发送完成

TI = 0//清除发送标志

SBUF = dat//发送当前数据

}

/*----------------------------

软件延时

----------------------------*/

void Delay(WORD n)

{

WORD x

while (n--)

{

x = 5000

while (x--)

}

}

正好做过,就给你吧!

*************************************

* *

* 主程序和中断程序入口 *

* *

*************************************

ORG 0000H

LJMPSTART

ORG 0003H

RETI

ORG 000BH

RETI

ORG 0013H

RETI

ORG 001BH

RETI

ORG 0023H

RETI

ORG 002BH

RETI

*************************************

* *

* 初始化程序中的各变量*

* *

*************************************

CLEARMEMIO: CLR A

MOV P2,A

MOV R0,#70H

MOV R2,#0DH

LOOPMEM:MOV @R0,A

INC R0

DJNZR2,LOOPMEM

MOV 20H,#00H

MOV A,#0FFH

MOV P0,A

MOV P1,A

MOV P3,A

RET

*************************************

* *

* 主 程 序 *

* *

*************************************

START: LCALL CLEARMEMIO 初始化

MAIN: LCALL TEST测量一次

LCALL DISPLAY 显示数据一次

AJMP MAIN

NOP PC值出错处理

NOP

NOP

LJMP START

*************************************

* 显 示 控 制 程 序*

*************************************

DISPLAY:JB 00H,DISP11

MOV R3,#04H 4路信号循环显示控制

MOV R0,#70H 显示数据初址70H~73H

MOV 77H,#00H 显示通道路数初值

DISLOOP1: LCALL TUNBCD显示数据转为三位BCD码存入76H、75H、74H(最大5.00v)

MOV R2,#0FFH 每路显示时间控制 4MS*255

DISLOOP2: LCALL DISP 调四位显示程序

LCALL KEYWORK1

DJNZR2,DISLOOP2

INC R0显示下一路

INC 77H 通道显示数加一

DJNZR3,DISLOOP1

RET

DISP11: MOV A,77H

SUBBA,#01H

MOV 77H,A

ADD A,#70H

MOV R0,A

DISLOOP11: LCALL TUNBCD显示数据转为三位BCD码存入7AH、79H、78H(最大5.00v)

MOV R2,#0FFH 每路显示时间控制 4MS*25

DISLOOP22: LCALL DISP 调四位显示程序

LCALL KEYWORK2

DJNZR2,DISLOOP22

INC 77H 通道显示数加一

RET

*************************************

* 显示数据转为三位BCD码程序 *

*************************************

显示数据转为三位BCD码存入76H、75H、74H(最大值5.00v)

TUNBCD: MOV A,@R0 255/51=5.00V运算

MOV B,#51

DIV AB

MOV 76H,A 个位数放入76H

MOV A,B 余数大于19H,F0为1,乘法溢出,结果加5

CLR F0

SUBBA,#1AH

MOV F0,C

MOV A,#10

MUL AB

MOV B,#51

DIV AB

JB F0,LOOP2

ADD A,#5

LOOP2: MOV 75H,A 小数后第一位放入75H

MOV A,B

CLR F0

SUBBA,#1AH

MOV F0,C

MOV A,#10

MUL AB

MOV B,#51

DIV AB

JB F0,LOOP3

ADD A,#5

LOOP3: MOV 74H,A 小数后第二位放入74H

RET

*************************************

*? 显?示 程 序 *

*************************************

共阳显示子程序,显示内容在74H—77H

DISP: MOV R1,#74H 共阳显示子程序,显示内容在74H—77H

MOV R5,#0FEH 数据在P1输出,列扫描在P3.0-P3.3

PLAY: MOV P1,#0FFH

MOV A,R5

ANL P3,A

MOVA,@R1

MOVDPTR,#TAB

MOVC A,@A+DPTR

MOVP1,A

JB P3.2,PLAY1 小数点处理

CLRP1.7 小数点显示(显示格式为XX.XX)

PLAY1: LCALL DL1MS

INCR1

MOVA,P3

JNBACC.3,ENDOUT

RL A

MOVR5,A

MOVP3,#0FFH

AJMP PLAY

ENDOUT: MOVP3,#0FFH

MOVP1,#0FFH

RET

TAB:DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0FFH

*************************************

*? ? 延时程序 *

*************************************

DL10MS: MOV R6,#0D0H 10MS延时子程序

DL1:MOV R7,#19H

DL2:DJNZ R7,DL2

DJNZ R6,DL1

RET

DL1MS: MOV R4,#0FFH 513+513=1MS

LOOP11: DJNZR4,LOOP11

MOV R4,#0FFH

LOOP22: DJNZR4,LOOP22

RET

*************************************

*? 电压测量(A/D)子程序 *

*************************************

一次测量数据4个,依次放入70H-73H单元中

TEST: CLR A 模数转换子程序

MOV P2,A

MOV R0,#70H转换值存放首址

MOV R7,#04H转换4次控制

LCALL TESTART 启动测试

WAIT: JB P3.7,MOVD 等A/D转换结束信号

AJMP WAIT

TESTART:SETBP2.3 测试启动

NOP

NOP

CLR P2.3

SETBP2.4

NOP

NOP

CLR P2.4

NOP

NOP

NOP

NOP

RET

MOVD: SETBP2.5 取A/D转换数据

MOV A,P0

MOV @R0,A

CLR P2.5

INC R0

MOV A,P2 通道地址加1

INC A

MOV P2,A

CJNEA,#04H,TESTEND等8路A/D转换结束

TESTEND:JC TESTCON

CLR A 结束恢复端口

MOV P2,A

MOV A,#0FFH

MOV P0,A

MOV P1,A

MOV P3,A

RET

TESTCON:LCALL TESTART

LJMPWAIT

*************************************

*? 按键检测子程序 *

*************************************

KEYWORK1: JNB P3.5,KEY1

KEYOUT: RET

KEY1: LCALL DISP 延时消抖

JB P3.5,KEYOUT

WAIT11: JNB P3.5,WAIT12

CPL 00H

MOV R2,#01H

MOV R3,#01H

RET

WAIT12: LCALL DISP 键释放等待时显示用

AJMPWAIT11

KEYWORK2: JNB P3.5,KEY1

JNB P3.6,KEY2

RET

KEY2: LCALL DISP 延时消抖用

JB P3.6,KEYOUT

WAIT22: JNB P3.6,WAIT21

INC 77H

MOV A,77H

CJNEA,#04H,KEYOUT11

KEYOUT11: JC KEYOUT1

MOV 77H,#00H

KEYOUT1:RET

WAIT21: LCALL DISP 键释放等待时显示用

AJMPWAIT22

END

附录3:

单片机C源程序清单

/*********************************************************************/

//四路电压表C程序

//使用keil C51 ver7.09

/*********************************************************************/

/*使用AT89C52单片机,12MHZ晶振,P0口读入AD值,P2口作AD控制,用共阳LED数码管

P1口输出段码,P3口扫描,最高位指示通道(0-7)。*/

#include "reg52.h"//52系列单片机定义文件

#include "intrins.h" //调用_nop_()延时函数用

#define ad_con P2 //AD控制口

#define addata P0 //AD数据计入读入口

#define DisdataP1//显示数据段码输出口

#define uchar unsigned char//无符号字符(8位)

#define uint unsigned int //无符号整数(16位)

sbit ALE=P2^3 //锁存地址控制位

sbit START=P2^4//启动一次转换位

sbit OE=P2^5 //0809输出数据控制位

sbit EOC=P3^7 //转换结束标志位

sbit DISX=Disdata^7//LED小数点

//

//

uchar code dis_7[11]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff}

/* 共阳七段LED段码表 "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "不亮" */

uchar code scan_con[4]={0xfe,0xfd,0xfb,0xf7} //四位列扫描控制字

uchar data ad_data[8]={0x00,0x00,0x00,0x00}//定义4个数据内存单元

uint data dis[5]={0x00,0x00,0x00,0x00,0x00} //定义4个显示数据单元、1个数据暂存单元

//

//

/********1毫秒延时子函数**********/

delay1ms(uint t)

{

uint i,j

for(i=0i<ti++)

for(j=0j<120j++)

}

//

//

/***********显示扫描子函数**********/

scan()

{

uchar k,n

int h

dis[3]=0x00//通道初值为0

for(n=0n<4n++) //每次显示4个数据

{

dis[2]=ad_data[n]/51 //测得值转换为三位BCD码,最大为5.00V

dis[4]=ad_data[n]%51 // 余数暂存

dis[4]=dis[4]*10 //计算小数第一位

dis[1]=dis[4]/51 //

dis[4]=dis[4]%51 //

dis[4]=dis[4]*10 //计算小数第二位

dis[0]=dis[4]/51 //

for(h=0h<500h++) //每个通道值显示时间控制(约1秒)

{

for(k=0k<4k++) //四位LED扫描控制

{

Disdata=dis_7[dis[k]]

if(k==2){DISX=0}

P3=scan_con[k]delay1ms(1)P3=0xff

}

}

dis[3]++//通道值加1

}

}

//

//

/*******0809AD转换子函数***********/

test()

{

uchar m

uchar s=0x00

ad_con=s

for(m=0m<4m++)

{

ALE=1_nop_()_nop_()ALE=0//转换通道地址锁存

START=1_nop_()_nop_()START=0//开始转换命令

_nop_()_nop_()_nop_()_nop_()//延时4微秒

while(EOC==0) //等待转换结束

OE=1ad_data[m]=addataOE=0s++ad_con=s//取AD值,地址加1

}

ad_con=0x00 //控制复位

}

//

//

/**************主函数****************/

main()

{

P0=0xff //初始化端口

P2=0x00

P1=0xff

P3=0xff

while(1)

{

scan() //依次显示4个通道值一次

test() //测量转换一次

}

}

//

//

//*********************结束**************************//

#include<stc89.h>

#include<intrins.h>

#define uchar unsigned char

#define uint unsigned int

uchar code table[]={

0x3f,0x06,0x5b,0x4f,

0x66,0x6d,0x7d,0x07,

0x7f,0x6f,0x77,0x7c,

0x39,0x5e,0x79,0x71,

0x00}

uchar led[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,0x00,0xFF}

sbit adrd=P3^7

sbit adwr=P3^6

sbit dula=P2^6

sbit wela=P2^7

uchar date1=0

uchar date2=50

uchar date3=100

uchar date4=150

uchar date5=200

uchar date6=255

uchar a,sz

void init()

void delay(uint z)

uchar adchushihua()

void shumaguan(uint shu)

void processing()

void main()

{

init()

while(1)

{

sz=adchushihua()

for(a=10a>0a--)

{

shumaguan(sz)

processing()

}

}

}

void init()

{

P0=0x7f

}

void delay(uint z)

{

uint x,y

for(x=zx>0x--)

for(y=110y>0y--)

}

uchar adchushihua()

{

uchar shuzhi

adwr=1

_nop_()

adwr=0

_nop_()

adwr=1

P1=0xff

adrd=1

_nop_()

adrd=0

_nop_()

shuzhi=P1

adrd=1

return shuzhi

}

void shumaguan(uint shu)

{

uchar bai,shi,ge

bai=shu/100

shi=shu%100/10

ge=shu%10

dula=1

P0=table[bai]

dula=0

P0=0xff

wela=1

P0=0x7e

wela=0

delay(5)

dula=1

P0=table[shi]

dula=0

P0=0xff

wela=1

P0=0x7d

wela=0

delay(5)

dula=1

P0=table[ge]

dula=0

P0=0xff

wela=1

P0=0x7b

wela=0

delay(5)

}

void processing()

{

if((sz>=date1)&&(sz<=date2))

{

P1=0xfe

}

else if((sz>=date2)&&(sz<=date3))

{

P1=0xfd

}

else if((sz>=date3)&&(sz<=date4))

{

P1=0xfb

}

else if((sz>=date4)&&(sz<=date5))

{

P1=0xf7

}

else if((sz>=date5)&&(sz<date6))

{

P1=0xef

}

else if(sz==date6)

{

P1=~P1

delay(20)

}

}

这个是我刚刚写的 根据你的需要 反正闲来无事 我写的比较笼统 需要你自己根据 自己的实际情况来判断确定 我只是利用AD简单的处理 成数码管显示的数字 你要是 转换成电压 那就把里面的变量 修改一下 我写的那个控制LED灯亮就不要动了 只是修改一下他前面定义的数字就可以 最后那个是我自己加上去的有点趣味性 希望对你有帮助


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7738240.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-09
下一篇 2023-04-09

发表评论

登录后才能评论

评论列表(0条)

保存