重要原理图
要想学好单片机,必须要识原理图才能懂得原理图,识的原理图,以下重要的模块:
CPU原理图:
LED模块:P2为低电平则LED点亮
#include<reg51.h>
//#define P2 (*((unsigned char *)(0xA0))) 特殊寄存器
void init_led(void) //初始化LED,LED全灭
{
P2=0xff;
}
void led_all_on(void) //点亮全部LED
{
P2=0;
}
void led_all_off(void) //关闭LED
{
P2=0xff;
}
void led_on(unsigned char n) //以16进制点亮LED,0为亮,1灭
{
P2=~n;
}
独立按键原理图 :GPIO口的输入用法,P3引脚为0则表示按键按下
#include <reg51.h>
#include "key.h"
void init_key(void) //按键的初始化
{
P1 |=0xf0;
P3 |=0x20;
}
int key_pressed(void) //判断哪个按键按下
{
if((P1 & (1<<4)) ==0)
{
return 1;
}
if((P1 & (1<<5)) ==0)
{
return 2;
}
else if((P1 & (1<<6)) ==0)
{
return 3;
}
else if((P1 & (1<<7)) ==0)
{
return 4;
}
else if((P3 & (1<<5)) ==0)
{
return 5;
}
else
{
return 0;
}
}
数码管原理图
#include <reg51.h>
#include "digiter.h"
void show_num(unsigned int n) // 显示1~9的其中的一个数值
{
unsigned char t[]={0x3f,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
P0=t[n];
delay(500);
P0=0;
delay(200);
}
void select_bit(char n) //选择哪个数码管
{
if(n>=4)
{
return ;
}
P1 &=0xf0;
P1 |=(1<<n);
}
void show_number(unsigned int n) //显示数据无符号整型n
{
int i=0;
while(n!=0)
{
select_bit(i++);
show_num(n%10);
n=n/10;
}
}
中断:
当中央处理器CPU正在处理某件事的时候外界发生了紧急事件请求,要求CPU暂停当前的工作,转而区处理这个紧急事件,处理完之后,再回到原来被中断的地方,继续原来的工作,这样的过程称为中断。
中断源:
请求CPU中断的请求源称为中断源。
中断执行流程:
中断向量表:
函数指针的数组
中断优先级:
要使用中断,必须要依照手册中所表示的寄存器来配合使用
其重要的寄存器有
void init_eint(void) //初始化中断
{
P3 |=(1<<2) | (1<<3);
IE |=(1<<7)|(1<<0) | (1<<2);
TCON |=(1<<0) | (1<<2);
}
void exit0_handler(void) interrupt 0 //中断0程序
{
delay(55);
n++;
}
定时器/计数器
其相关寄存器
定时器/计数器控制寄存器TCON
定时器/计数器工作模式寄存器TMOD
用定时的方式根据按键来控制蜂鸣器的频率
void init_timer(void) //初始化定时器
{
IE|=(1<<7)|(1<<1);
TMOD=0xf1;
TH0=n>>8;
TL0=n;
}
int main(void)
{
int k;
init_timer();
while(1)
{
int key=key_pressed();
if(key==1)
{
TCON|=(1<<4);
n=63035;
}
else if(key==2)
{
TCON|=(1<<4);
n=64285;
}
else if(key==3)
{
TCON|=(1<<4);
n=64702;
}
else if(key==4)
{
TCON|=(1<<4);
n=64910;
}
else
{
}
}
}
void timer0(void) interrupt 1 定时器1中断
{
P2^=(1<<1);
TH0=n>>8;
TL0=n;
}
串口通信
- 单工模式(Simplex Communication):主机间通信时如果一方固定为发送端另外一方固定为接收端,通过一根总线实现数据通信。这种通信方式就像是你只能听别人说话,但无法回答他们一样,只能单向传递信息。
- 半双工通信(Half-Duplex Communication)是一种通信方式,其中数据传输可以在两个方向之间交替进行,但不能同时进行。换句话说,通信双方可以既发送数据又接收数据,但不能同时进行这两种操作。比方说,就像你可以和别人交替说话和倾听对方说话一样。当你在说话时,对方在听你说;当对方在说话时,你在倾听对方。这种方式允许双方之间在发送和接收数据之间切换,但不能同时进行。半双工通信常用于对话式交流和一些简单的通信场景中。
- 全双工通信(Full-Duplex Communication)是一种通信方式,其中数据传输可以同时在两个方向进行,允许通信双方同时发送和接收数据,实现双向通信。就像打电话一样,你可以同时说话也可以听对方说话,双方可以同时进行数据传输,实现双向沟通。
- TTL(Transistor-Transistor Logic)通常指的就是芯片引脚产生的电压,这个电压值跟选择的芯片有关,在51单片机系统下是5v;在2440下是3.3v等等。5vTTL通信距离通常被限制在10~20米之间,如果需要更远的距离,怎么解决呢?
- 为解决这个问题IEEE(Institute of Electrical and Electronics Engineers)颁布了RS232标准,其中规定了:
逻辑高电平(逻辑1):在-3V到-15V之间
逻辑低电平(逻辑0):在+3V到+15V之间
收发主机间有三根线,分别是收、发和地,因此RS232是全双工的。
理论上RS232能够传输20~30米。
3.同理RS485使用两根信号线(A和B)来传输数据,通过比较A和B之间的电压差来识别信息,电压范围分别为+7V到+12V和-7V到-12V。正电压表示高电平,负电压表示低电平。这种差分信号传输方式提高了抗干扰能力。RS485的传输距离可达1200米,适用于大范围的数据传输需求。由于采用的是压差,RS485在传输数据的某一时刻,两根线都要用到,所以它是半双工的。
软件代码
#include <reg51.h>
#include "uart.h"
#include "digiter.h"
void init_uart(void) //初始化串口
{
unsigned char t;
t=SCON;
t&=~(1<<7);
t|=(1<<6);
t|=(1<<4);
SCON=t;
PCON|=(1<<7);
t=TMOD;
t|=(1<<5);
t&=~(1<<4);
t&=~(3<<6);
TMOD=t;
TL1=243;
TH1=243;
TCON|=(1<<6);
IE|=(1<<4)|(1<<7);
}
void send_char(char buff) //发送一个字节的数据
{
SBUF=buff;
while((SCON &(1<<1)) ==0);
SCON &=~(1<<1);
}
void send_buffer(const char *buff,unsigned int len) //发送一个字符串
{
while(len--)
{
send_char(*buff++);
}
}
到这个地方再看看单片机的时序图,学会其代码,就入门了
DS1820原理图
初始化时序
写时序
读时序
代码实现如上:
#include <reg51.h>
#include <intrins.h>
#include <stdio.h>
#include "uart.h"
#include "delay.h"
#include "string.h"
#define ds18b20_set (P3 |=(1<<7)) //低电平
#define ds18b20_clr (P3 &=~(1<<7)) //高电平
#define ds18b20_tst ((P3 & (1<<7)) !=0) //判断电平高低
int reset_ds18b20(void) //初始化
{
int t;
ds18b20_clr;
Delay10us(70);
ds18b20_set;
Delay10us(5);
t=0;
while(ds18b20_tst && t<30)
{
Delay10us(1);
t++;
}
if(t>=30)
{
return 0;
}
t=0;
while(!ds18b20_tst && t<30)
{
Delay10us(1);
t++;
}
if(t>=30)
{
return 0;
}
return 1;
}
void ds18b20_write(char dat) //写操作
{
int i;
for(i=0;i<8;++i)
{
if(dat & 0x01)
{
ds18b20_clr;
_nop_();
_nop_();
ds18b20_set;
Delay10us(5);
}
else
{
ds18b20_clr;
Delay10us(5);
ds18b20_set;
}
dat>>=1;
}
}
unsigned char ds18b20_read(void) //读操作
{
unsigned char ret=0;
int i;
for(i=0;i<8;++i)
{
ds18b20_clr;
_nop_();
_nop_();
ds18b20_set;
_nop_();
_nop_();
_nop_();
_nop_();
if(ds18b20_tst)
{
ret |= (1<<i);
}
Delay10us(4);
}
return ret;
}
float geTemperature(void) //获得其温度
{
unsigned char tl, th;
short t;
reset_ds18b20();
ds18b20_write(0xCC);
ds18b20_write(0x44);
Delay1ms(75);
reset_ds18b20();
ds18b20_write(0xCC);
ds18b20_write(0xBE);
tl = ds18b20_read();
th = ds18b20_read();
t = th << 8;
t |= tl;
return t * 0.0625;
}