51 单片机的 IO 接口,必须使用直接寻址方式。
所以,在 C 语言中,不可使用指针对 IO 接口进行 *** 作。
凡是必须直接寻址的,如:TMOD、IE、IP 等等,都不可使用指针。
还有位地址,也不行。
//DS从机程序
#include <reg52h>
#include <intrinsh>
#define uchar unsigned char
#define uint unsigned int
#define SLAVE 0x01
#define BN 6
sbit LCD_RS = P2^5; /定义LCD控制端口/
sbit LCD_RW = P2^6;
sbit LCD_EN = P2^7;
sbit DS1=P1^0;
sbit DS2=P1^1;
sbit key3=P3^5;
sbit tem=P3^3;
sbit win=P3^4;
sbit key1=P3^6;
sbit key2=P3^7;
uint temp1,temp2,tempH,tempL; // variable of temperature
uchar flag1,aa,we;
uchar A1,A2,A3,A4,B1,B2,B3,B4; // sign of the result positive or negative
uchar dis1[16]={76,45,84,'0','0','','0',32,32,72,45,84,'0','0','','0'};
uchar dis2[16]={48,49,32,'0','0','','0',32,32,48,50,32,'0','0','','0'};
uchar code tab[] = {'0','1','2','3','4','5','6','7','8','9'};
uchar trbuf[6];
bit tready;
bit rready;
void str(void);
void sre(void);
void delay(int ms)
{
int i;
while(ms--)
{
for(i = 0; i< 250; i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
//
/ /
/检查LCD忙状态 /
/lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。 /
/ /
//
bit lcd_busy()
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
_nop_();
_nop_();
_nop_();
_nop_();
result = (bit)(P0&0x80);
LCD_EN = 0;
return result;
}
//
/ /
/写指令数据到LCD /
/RS=L,RW=L,E=高脉冲,D0-D7=指令码。 /
/ /
//
void lcd_wcmd(uchar cmd)
{
while(lcd_busy());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = cmd;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN = 1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN = 0;
}
//
/ /
/写显示数据到LCD /
/RS=H,RW=L,E=高脉冲,D0-D7=数据。 /
/ /
//
void lcd_wdat(uchar dat)
{
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN = 1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN = 0;
}
//
/ /
/ 设定显示位置 /
/ /
//
void lcd_pos(uchar pos)
{
lcd_wcmd(pos|0x80); //数据指针=80+地址变量
}
//
/ /
/ LCD初始化设定 /
/ /
//
void lcd_init()
{
lcd_wcmd(0x38); //162显示,57点阵,8位数据
delay(5);
lcd_wcmd(0x38);
delay(5);
lcd_wcmd(0x38);
delay(5);
lcd_wcmd(0x0c); //显示开,关光标
delay(5);
lcd_wcmd(0x06); //移动光标
delay(5);
lcd_wcmd(0x01); //清除LCD的显示内容
delay(5);
lcd_wcmd(0x06); //向右移动光标
delay(5);
}
//
/ /
/ 闪动子程序 /
/ /
//
void flash()
{
delay(600); //控制停留时间
lcd_wcmd(0x08); //关闭显示
delay(200); //延时
lcd_wcmd(0x0c); //开显示
delay(200); //延时
lcd_wcmd(0x08); //关闭显示
delay(200); //延时
lcd_wcmd(0x0c); //开显示
delay(200);
}
/void delay(uint count) //delay
{
uint i;
while(count)
{
i=100;
while(i>0)
i--;
count--;
}
} /
///////功能:串口初始化,波特率9600,方式1///////
void Init(void)
{
TMOD=0x20;
TL1=0xfd;
TH1=0xfd;
PCON=0x00;
TR1=1;
SCON=0xf0;
ES=1;
EA=1;
}
void dsreset(uchar DS) //send reset and initialization command 18B20复位,初始化函数
{
uint i;
if(DS==1)
{
DS1=0;
i=103;
while(i>0)i--;
DS1=1;
i=4;
while(i>0)i--;
}
if(DS==2)
{
DS2=0;
i=103;
while(i>0)i--;
DS2=1;
i=4;
while(i>0)i--;
}
}
bit tmpreadbit(uchar DS) //read a bit 读DS2 1位数据函数
{
uint i;
bit dat;
if(DS==1)
{
DS1=0;i++; //i++ for delay
DS1=1;i++;i++;
dat=DS1;
i=8;while(i>0)i--;
}
if(DS==2)
{
DS2=0;i++; //i++ for delay
DS2=1;i++;i++;
dat=DS2;
i=8;while(i>0)i--;
}
return (dat);
}
uchar tmpread(uchar DS) //read a byte date 读1字节函数
{
uchar i,j,dat;
dat=0;
if(DS==1)
{
for(i=1;i<=8;i++)
{
j=tmpreadbit(1);
dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里
}
}
if(DS==2)
{
for(i=1;i<=8;i++)
{
j=tmpreadbit(2);
dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里
}
}
return(dat);
}
void tmpwritebyte(uchar dat,uchar DS) //write a byte to ds18b20 向1820写一个字节数据函数
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(DS==1)
{
if(testb) //write 1
{
DS1=0;
i++;i++;
DS1=1;
i=8;while(i>0)i--;
}
else
{
DS1=0; //write 0
i=8;while(i>0)i--;
DS1=1;
i++;i++;
}
}
if(DS==2)
{
if(testb) //write 1
{
DS2=0;
i++;i++;
DS2=1;
i=8;while(i>0)i--;
}
else
{
DS2=0; //write 0
i=8;while(i>0)i--;
DS2=1;
i++;i++;
}
}
}
}
void tmpchange(uchar DS) //DS18B20 begin change 开始获取数据并转换
{
if(DS==1)
{
dsreset(1);
delay(1);
tmpwritebyte(0xcc,1); // address all drivers on bus 写跳过读ROM指令
tmpwritebyte(0x44,1);
} // initiates a single temperature conversion 写温度转换指令
if(DS==2)
{
dsreset(2);
delay(1);
tmpwritebyte(0xcc,2); // address all drivers on bus 写跳过读ROM指令
tmpwritebyte(0x44,2);
} // initiates a single temperature conversion 写温度转换指令
}
uint tmp1(void) //get the temperature 读取寄存器中存储的温度数据
{
float tt;
uchar a,b;
dsreset(1);
delay(1);
tmpwritebyte(0xcc,1);
tmpwritebyte(0xbe,1);
a=tmpread(1); //读低8位
b=tmpread(1); //读高8位
temp1=b;
temp1<<=8; //two byte compose a int variable 两个字节组合为1个字
temp1=temp1|a;
tt=temp100625; //温度在寄存器中是12位,分辨率是00625
temp1=tt10+05; //乘10表示小数点后只取1位,加05是四折五入
//temp1=temp1+5; //误差补偿
return temp1;
}
uint tmp2( void) //get the temperature 读取寄存器中存储的温度数据
{
float tt;
uchar a,b;
dsreset(2);
delay(1);
tmpwritebyte(0xcc,2);
tmpwritebyte(0xbe,2);
a=tmpread(2); //读低8位
b=tmpread(2); //读高8位
temp2=b;
temp2<<=8; //two byte compose a int variable 两个字节组合为1个字
temp2=temp2|a;
tt=temp200625; //温度在寄存器中是12位,分辨率是00625
temp2=tt10+05; //乘10表示小数点后只取1位,加05是四折五入
//temp2=temp2+5; //误差补偿
return temp2;
}
void delay10ms() //delay
{
uchar a,b;
for(a=10;a>0;a--)
for(b=60;b>0;b--);
}
uchar display(uint temp1,uint temp2) //显示程序
{
uchar i;
A1=temp1/100;
A2=temp1%100/10;
A3=temp1%100%10;
B1=temp2/100;
B2=temp2%100/10;
B3=temp2%100%10;
trbuf[0]=A1;
trbuf[1]=A2;
trbuf[2]=A3;
trbuf[3]=B1;
trbuf[4]=B2;
trbuf[5]=B3;
dis1[3]=tab[tempL10/100];
dis1[4]=tab[tempL10%100/10];
dis1[6]=tab[tempL10%100%10];
dis1[12]=tab[tempH10/100];
dis1[13]=tab[tempH10%100/10];
dis1[15]=tab[tempH10%100%10];
dis2[3]=tab[A1];
dis2[4]=tab[A2];
dis2[6]=tab[A3];
dis2[12]=tab[B1];
dis2[13]=tab[B2];
dis2[15]=tab[B3];
delay(1);
lcd_pos(0); //设置显示位置为第一行的第1个字符
delay(2);
for(i=0;i<16;i++)
{
lcd_wdat(dis1[i]);
}
delay(2);
lcd_pos(0x40);
delay(2);
for(i=0;i<16;i++)
{
lcd_wdat(dis2[i]);
}
return (A1,A2,A3,B1,B2,B3);
}
void TemC()
{
if(temp1<=(tempL10)||temp2<=(tempL10)) tem=0;
else tem=1;
if (temp1>=(tempH10)||temp2>=(tempH10)) win=0;
else win=1;
}
uchar chan()
{
if(key1==0)
{
tempL++;
while(key1==0);
if(tempL>35)
tempL=0;
}
if(key2==0)
{
tempH++;
while(key2==0);
if(tempH>35)
tempH=0;
}
return (tempH,tempL);
}
//
void main()
{ //uchar a;
//uchar i;
delay(10);
lcd_init();
Init();
tempH=35;
tempL=15;
while(1)
{
tmpchange(1);
tmpchange(2);
tmp1();
tmp2();
chan();
TemC();
display(temp1,temp2);
tready=1;
rready=1;
}
}
void ssio(void)interrupt 4
{
uchar a;
RI=0;
ES=0;
if(SBUF!=SLAVE)
{
ES=1;
goto reti;
}
SM2=0;
SBUF=SLAVE;
while(TI!=1);
TI=0;
while(RI!=1);
RI=0;
if(RB8==1)
{
SM2=1;
ES=1;
goto reti;
}
a=SBUF;
if(a==0x02)
{
if(tready==1)
SBUF=0x02;
else
SBUF=0x00;
while(TI!=1);
TI=0;
str();
goto reti;
}
else
{
SBUF=0x08;
while(TI!=1);
TI=0;
SM2=1;
ES=1;
}
reti:RI=0;
SM2=1;
ES=1;
}
void str(void)
{
uchar i;
tready=0;
while(1)
{
tmpchange(1);
tmpchange(2);
tmp1();
tmp2();
chan();
TemC();
display(temp1,temp2);
for(i=0;i<BN;i++)
{
SBUF=trbuf[i];
while(TI!=1);
TI=0;
}
while(RI!=1);
RI=0;
if(RB8==1)goto loop;
}
loop:SM2=1;
ES=1;
}
单片机的io口设置成输出或输入状态就是给这个io口赋值为0或1。但是这个0或1并代表是输入还是输出状态,这要取决于你连接这个口的是什么器件,或者说取决于你这个口要实现的是输入还是输出状态。比如点亮一个led灯,首先一定是io口输出一个状态才能让灯亮对吧,那么给0还是给1得看电路。再比如按键,这时就是给io口输入了。是0还是1也看电路。
最后一个特殊就是ad采集,这肯定是输入吧,但是不能单纯的理解为给个0或1了。再比如pwm这肯定是输出,但也不能单纯的理解为给个0或1。
说了这么多,意思就是看你要让这个口实现的是输入还是输出状态,当你确定了,那么这个口的状态也就被确定了。
以上就是关于51单片机如何使用指针控制IO全部的内容,包括:51单片机如何使用指针控制IO、51单片机两个I/O口分别接ds18b20程序、怎样将51单片机IO口设置成输出状态或输入状态呢希望高手能给通俗易懂的解答一下!!!回答好了可以等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)