51单片机
采用宏定义文件absacc.h
定义绝对地址变量。
格式:
#define 变量名 XBYTE[地址常数]
说明:
XBYTE宏允许用户访问8051外部数据存储器中的某一字节。
PBYTE宏允许用户按页访问8051外部数据存储器中某一字节
CBYTE宏允许用户访问8051程序存储器中某一字节
DBYTE宏允许用户访问8051内部数据存储器中某一字节
采用指针访问呢片外RAM绝对地址
格式:
数据类型 [存储类型1]*[存储类型2] 变量名[=地址常数]; P64
demo:
unsigned char xdata *PORT = 0x1000;
采用_at_
关键字访问片外ram绝对地址
使用_at_
可对指定存储器空间的绝对地址定位,但使用_at_
定义的变量只能是全局变量。
格式:
变量类型 [存储类型] 变量名 _at_ 常量;
demo:
unsigned char xdata xram[0x80] _at_ 0x1000;
两类:
可编程IO扩展芯片 - 功能可由控制字设置
锁存/缓冲器接口芯片 - 功能固定不变
选用芯片的原则:输入三态、输出锁存
## ADC0809
#### 转换步骤
1.ALE信号上升沿,锁存地址并选中相应通道。 2.START信号下降沿开始启动AD转换,AD转换期间START为低电平 3.EOC信号由低变高时,表示AD转换结束 4.OE信号由低变高时,允许D0-D7输出转换结果
注意:实际使用时,将ALE、START合二为一<br>
模拟通道地址:
## ADC0832
### DAC性能指标
1.分辨率<br>
V0=-B*(Vref/256)<br>
0832分辨率8位<br>
2.转换时间<br>
将一个数字量转换位稳定模拟信号所需时间<br>
0832转换时间位1us<br>
3种控制方式:
直通方式 --两个寄存器都处在直通状态 单缓冲方式 - 一个寄存器处于直通,另一个受控 双缓冲 - 两个寄存器都在受控状态
## 编程题
### 1.利用定时器产生一方波信号,要求采用查询或终端方式编写
#### 查询法
```c
#include <reg51.h>
sbit P1_0=P1^0;
void main(){
TMOD = 0x01;
TR0=1;
while(1){
TH0=0xff;
TL0=-125;
while(!TF0);
TF0=0;
P1_0=!P1_0;
}
}
void main(){
TMOD=0x01;
TH0=0xff;
TL0=-125;
EA=1;
ET0=1;
TR0=1;
while(1);
}
void int() interrupt 1{
TH0=0xff;
TL0=-125;
P1_0=!P1_0;
}
#include<intrins.h>
sbit START=P2^5;
sbit EOC=P2^6;
sbit OE=P2^7;
void main(){
ulong temp,val;
while(1){
START=1; //启动转换
_nop_();
START=0;
while(EOC==0); //等待转换完成
OE=1;
P1=0xff;
temp=P1; //读数据
OE=0;
val=(1000*5*temp/255+5)/10; //四舍五入
display(val);
}
}
void delayms(uint n){
uint i,j;
for(i=n;i>0;i--)
for(j=123;j>0;i--)
}
void main(){
uchar i,led=0x7f;
while(1){
for(i=0;i<8;i++){
P0=led;
delayms(200);
led=(led>>1)|0x80; //循环右移
}
}
}
发送
void main(){
uchar c=0,temp;
SCON=0x50; //SM0=0,SM1=1 方式1;REN=1,允许接收;SM2=TI=RI=0;
TMOD=0x20; //TI定时方式2
TH1=TL1=0xf4 //波特率2400bps
TR1=1;
while(1){
SBUF=c; //发送
while(!TI); //等待发送完毕
TI=0;
while(!RI); //等待从机返回
RI=0; //收到清零
temp=SBUF;
if(temp==c){
P2=x;
if(++c>=16) c=0;
delay();
}
}
}
接收
uchar r=0;
void main(){
SCON=0x50;
TMOD=0x20;
TH1=TL1=0xf4;
TR1=1;
EA=1;
ES=1;
while(1);
}
void int() interrupt 4{
RI=0;
ES=0;
r=SBUF;
P2=r;
SBUF=r;
while(TI==0);
TI=0;
ES=1;
}
发送
void main(){
uchar count=0;
P2=0x00;
TMOD=0x20; //定时器1方式2
TH1=TL1=0xfd; //自动重装,波特率9600
SCON=0xd0; //串口方式3,允许接收
TR1=1;
while(1){
ACC=count;
TB8=P;
SBUF=count;
while(TI==0);
TI=0;
while(RI==0);
RI=0;
if(RB8==1){
P2=count;
if(++count>15) count=0;
delay();
}
}
}
接收
void main(){
uchar rec;
P2=0x00;
TMOD=0x20; //定时器1方式2
TH1=TL1=0xfd;
SCON=0xd0;
TR1=1;
while(1){
while(RI==1) //是否收到数据
{
RI=0;
rec=SBUF;
ACC=rec; //讲数据放入累加器,以便于奇偶校验
if(P==RB8) TB8=1; //奇偶校验位和接收到的一致,则讲发送的奇偶校验位赋值1,否则0,一遍发送放处理接收到的数据
else TB8=0;
SBUF=rec;
while(TI==0);
TI=0;
P2=rec;
}
}
}
char mod[] = {0x38,0x5b}; //LED字模L2
void main(){
char point=0;
while(1){
P3=2-point; //输出LED位码
P2=mod[point];
point=1-point;
delay();
}
}
char mod[]={...}; //字模
char key[]={...}; //键模
char getkey(){
char scan[]={0xef,0xdf,0xbf,0x7f};
char i=0,j=0;
for(i=0;i<4;i++){
P2=scan[i];
if((P2&0x0f)!=0x0f){
for(j=0;j<16;j++){
if(buf[j]==P2) return j;
}
}
}
return -1;
}
void main(){
char key=0;
P0=0x00;
while(1){
key=getkey();
if(key!=-1) P0=mod[key];
}
}
如果是用中断法:
void getkey() interrupt 0{
char scan[]={0xef,0xdf,0xbf,0x7f};
char i=0,j=0;
for(i=0;i<4;i++){
P2=scan[i];
for(j=0;i<16;j++){
if(buf[j]==P2){
P0=mod[j];
break;
}
}
}
P2=0x0f;
}
void main(){
P0=0x00;
IT0=1; //脉冲触发
EX0=1; //INT0允许
EA=1;
P2=0x0f;
while(1);
}
将由IN7通道输入的模拟量信号进行AD转换,结果以16进制显示,设工作时钟频率为5kHz
查询法1
#include<absacc.h>
#define AD_IN7 XBYTE[0xfeff] //IN7通道访问地址
sbit busy=p3^3; //AD转换结束标志
void main(){
while(1){
AD_IN7=0;
while(busy==1);
P1=AD_IN7; //转换数据显示
}
}
查询法2
sbit START=P3^6;
sbit P20=P2^0;
sbit EOC=P3^7;
void main(){
while(1){
P20=0; START=1;START=0;START=1; //启动AD转换
while(EOC==1);
OE=0; P1=P0; OE=1; //读转换结果
}
}
输出一路正弦波
查询法:
include<math.h>
int num;
void main(){
while(1){
for(num=0;num<360;num++)
P2=127 + 127*sin((float)num / 180 *PI);
}
}
中断法:
#include<adsacc.h>
void int() interrupt 2{
P1=AD_IN7;
AD_IN7=0;
}
void main(){
IT1=1; //边沿触发
EA=1;
EX1=1;
AD_IN7=0;
while(1);
}
输出一路三角波
#include<absacc.h>
#define DAC XBYTE[0xfeff] //设置0832访问地址
char num;
void main(){
while(1){
for(num=0;num<255;num++) //上升段波形
DAC=num; //转换输出
for(num=255;num>0;num--) //下降段波形
DAC=num; //转换输出
}
}
实现两路锯齿波同步发生
#define DAC1 XBYTE[0xfeff] //DAC1输入锁存器地址
#define DAC2 XBYTE[0xfdff] //DAC1输入锁存器地址
#define DACOUT XBYTE[0xefff] //DAC寄存器共同地址
void main(){
uchar num;
while(1){
for(num=0;num<=255;num++){
DAC1=num; //上锯齿送入1
DAC2=255-num; //下锯齿送入2
DACOUT=num; //两路同时进行DA转换
}
}
}