第八届客观题(部分):
8051单片机堆栈指针的作用是:指明栈顶的位置
单片机和PC通讯使用MAX232芯片为了电平转换
空闲状态下,Tx引脚上电平为高
使用非整数的晶振是为了获得精准的波特率
通讯距离为800M时候使用RS485
串口TTL 几M RS-232 30M CAN BUS 10KM
I2C在读写操作时开始信号为SCL为高电平期间,SDA由高变为低
当电路有用信号为某一固定频率时候,选用带通滤波器
直流电源的滤波电路宜选用低通滤波器
pdata unsigned char 和 xdata unsigned char 分配在外部的RAM中
PWM功能的单片机可以通过滤波器实现DAC功能
15F61S2可以使用内部RC振荡器,也可以使用外部晶振工作
IO:对IO口直接赋值操作
MM的代码量比较小:存储器映射
温度芯片:具体功能我也不用过多解释了,芯片手册都有简单贴一下指令集:
代码可以实现每隔一秒刷新实时温度
因为在比赛的时候部分驱动代码是给出的所以我们在操作的时候只需要编写温度转换函数:
ds18b20.v:
#ifndef __DS18B20_H
#define __DS18B20_H
#include
//单总线延时函数
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
unsigned char temget();
void Delay500us();
#endif
ds18b20.c:
#include "stc15f2k60s2.h"
#include
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0; i<8; i++);
}
}
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//DS18B20设备初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
//--------------------------------------------------
//------------这部分代码自己编写----------------------
unsigned char temget()
{
unsigned char temp;
unsigned char low,high;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay500us();
Delay500us();
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low=Read_DS18B20();
high=Read_DS18B20();
temp=high<<4;
temp |= (low>>4);
return temp;
}
void Delay500us() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 6;
j = 93;
do
{
while (--j);
} while (--i);
}
在main.c中:
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
uchar seg[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e,
0xff
};
uchar temp=0;
uint tim;
uchar yi=16, er=16,san=12;
uchar guan=16;
uchar flag=0;
void allinit();
void display(uchar yi,er,san,si,wu,liu,qi,ba);
void Delay1ms();
void Delayms(uint ms);
void Timer0Init();
void main()
{
allinit();
Timer0Init();
while(1)
{
display(yi,er,san,guan,guan,guan,guan,guan);
}
}
void allinit()
{
P2=0xa0;P0=0x00;
P2=0x80;P0=0xff;
P2=0xe0;P0=0xff;
P2=0xc0;P0=0xff;
}
void display(uchar yi,er,san,si,wu,liu,qi,ba)
{
P2=0xe0;//段选
P0=seg[yi];
P2=0xc0;//位选
P0=0x01;
Delay1ms();
Delay1ms();Delay1ms();
P2=0xe0;//段选
P0=seg[er];
P2=0xc0;//位选
P0=0x02;
Delay1ms();Delay1ms();Delay1ms();
P2=0xe0;//段选
P0=seg[san];
P2=0xc0;//位选
P0=0x04;
Delay1ms();Delay1ms();Delay1ms();
P2=0xe0;//段选
P0=seg[si];
P2=0xc0;//位选
P0=0x08;
Delay1ms();Delay1ms();Delay1ms();
P2=0xe0;//段选
P0=seg[wu];
P2=0xc0;//位选
P0=0x10;
Delay1ms();Delay1ms();Delay1ms();
P2=0xe0;//段选
P0=seg[liu];
P2=0xc0;//位选
P0=0x20;
Delay1ms();Delay1ms();Delay1ms();
P2=0xe0;//段选
P0=seg[qi];
P2=0xc0;//位选
P0=0x40;
Delay1ms();Delay1ms();Delay1ms();
P2=0xe0;//段选
P0=seg[ba];
P2=0xc0;//位选
P0=0x80;
Delay1ms();Delay1ms();Delay1ms();
}
void Delay1ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
void Delayms(uint ms) //@11.0592MHz
{
unsigned char i, j,k;
for(k=ms;k>0;k--)
{
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
}
void Timer0Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA = 1;//总中断开关
ET0 = 1;//定时器0中断开始
}
void timer0() interrupt 1
{
tim++;
if(tim==1000)
{
tim=0;
temp=temget();
yi=temp%100/10;
er=temp%10;
}
}
中断的优先级问题:
interrupt1是中断序号 这是定时器0中断的意思 只要用定时器0中断 必须用此句。
interrupt 1是定时器0
interrupt 0 外中断0 interrupt2 外中断1
interrupt 3 定时器1
interrupt 4 串行口中断