嵌入式 - 基础

存储器

RAM(随机存储器)

易失性存储器:掉电丢失数据
存取速度快

  • SRAM(静态RAM):电路存储数据;速度最快,容量小
  • DRAM(动态RAM):电容(充放电)存储数据;容易漏电,需要扫描电路,成本低,容量大

ROM(只读存储器)

非易失性存储器:掉电不丢失数据
存取速度慢

  • Mask ROM(掩膜ROM):早起ROM,用电路存储数据 (芯片做好就是这个电路,读出来的就是这个数据)
  • PROM(可编程ROM):生产出来之后,只能写入一次,不能再次更改
  • EPROM(可擦除可编程ROM):可以擦除(但是需要紫外线照射擦除)
  • E2PROM(电可擦除可编程ROM):直接控制程序可以擦除,
  • Flash(闪存):现代ROM
  • 硬盘、软盘、光盘

在这里插入图片描述

EEPROM / FLASH

擦除单位:EEPROM支持按字节单位的写入和擦除,这意味着它可以单独擦写某一个字节而不影响其他字节。而FLASH通常以块或扇区为单位进行擦写,这要求在修改一个扇区中的某些数据时,必须重写整个扇区。
应用场景:EEPROM适用于存储小量的数据,如系统设置、用户配置信息等。而FLASH则适用于存储大量的数据,如固件、操作系统、音频和视频文件等
功耗:EEPROM 在读取数据时需要较低的功耗,而在擦除和编程时需要较高的功耗。Flash 在读取和编程时通常需要较低的功耗,但在擦除时需要较高的功耗
擦写和编程方式:EEPROM 的擦除和编程速度较慢,而 Flash 的擦除和编程速度更快

补充:FLASH只能按快擦写,不能按位擦写
想让FLASH按位擦写,就需要将FLASH原来的数据备份一份,再修改其中想要修改的位,再按块擦除,最后将写好的数据再烧录回原块中

IO口/寄存器/CPU

IO口电平和寄存器之间的交互可以通过以下步骤进行:

输出数据到IO口:当CPU需要向外部设备输出数据时,它会将数据写入指定的寄存器。这个寄存器通常称为输出寄存器或数据寄存器。CPU将要输出的数据写入到该寄存器中。

控制IO口电平:一旦数据被写入输出寄存器,CPU需要通过控制信号来改变IO口的电平状态。通常,CPU会通过控制寄存器或控制线信号来发出特定的命令,以控制IO口电平的变化。

IO口电平的改变:根据CPU发出的控制信号,IO口的电平会相应地改变。例如,如果CPU要将IO口设置为高电平,相关的控制信号会使外部设备电平变为高电平。反之,如果CPU要将IO口设置为低电平,控制信号会使外部设备电平变为低电平。

输入数据到寄存器:当外部设备的电平状态发生变化时(例如,另一个设备向CPU发送数据),IO口的电平变化会被检测到,并通过相应的电路传输到输入寄存器或数据寄存器。CPU可以通过读取该寄存器来获取输入的数据。

总结起来,CPU通过写入输出寄存器来设置数据的传输值,通过控制信号来控制IO口电平的改变,外部设备根据电平状态的变化将数据输入到输入寄存器或数据寄存器,CPU再通过读取该寄存器来获取输入的数据。这样实现了IO口电平和寄存器之间的交互。

定时器

https://www.bilibili.com/video/BV1k84y1v7q9/?spm_id_from=333.788&vd_source=7155082256127a432d5ed516a6423e20

51原理图
在这里插入图片描述
在这里插入图片描述

定时器/计数
在这里插入图片描述

编程实现
在这里插入图片描述

例子 - 定时器控制流水灯

#include <REGX52.H>

void main()
{
	/* NOTE: variable must declare in block front*/
	unsigned char k,n,i;
	unsigned short timer_ms;
	unsigned short initValue;
	n=0x01;
	k=0;
	
	/* setp1: config Timer register work mode */ 
  /* 0000 0001 -> T1(0000); T0(0001):: 
	 * GATE: 0 startup only with software
	 * C/T:  0 use to on timer 
	 * M1,M0: 0,1 : use TH0 and TL0
	 */
	TMOD=0x01;
	
	/* step2: set init value*/
	timer_ms=50; // 50ms
	initValue=65536-timer_ms*1000;
	TH0=(unsigned char)((initValue>>8) & 0xFF);
	TL0=(unsigned char)(initValue & 0xFF); 
	
	/* step3: start timer, if this timer is time out,the bit TF0 is 1*/
	TR0=1; // 0 is stop ; 1 is start
	
	while (1)
	{
		// left bit trans
		n=0x01;
		
		for (i=0;i<8;i++) // set 8 led 
		{
			P2=~n; // set led light
		
			while (k<10) // 50ms *10 = 500ms is 0.5s
			{
				/* setp4: wait timer time out*/	
				while (TF0==0); // 
				
				/* setp5: reset init value */
				TH0=(unsigned char)((initValue>>8) & 0xFF);
				TL0=(unsigned char)(initValue & 0xFF); 
				TF0=0;
				k++;
			}
			
			// the next led
			k=0;
			n=n<<1;
		}	
		
	}
}

定时器与中断

在这里插入图片描述

定时器与计数器

时钟系统由外部引脚提供的时候,就是计数器

定时器系统时钟

系统时钟就是晶振周期,不等于机器周期
对于分频的系统时钟,12T表示12分频,对于晶振周期是12MHZ的时钟系统,12分频后就是1MHZ,一个机器周期就是1us(1微秒)

中断

在这里插入图片描述

工作流程

其中一步:程序记录在ROM中, 记录断点就是记录程序语句被打断的存放的寄存器的地址(将要执行的中断语句地址,压入堆栈,中断程序返回后,再弹出堆栈)

在这里插入图片描述

中断源

引起CPU中断的根源:中断源
用于中断(打断)程序

中断优先:
分时操作:CPU分时执行I/O操作
实时响应:立即执行中断响应
可靠性

51单片机

一共有五个中断源

在这里插入图片描述
在这里插入图片描述

优先级

当多个中断源对CPU执行中断请求的时候,CPU根据中断源的优先级执行对应的中断请求
单片机内有默认的优先级别,也可以修改对应寄存器的值来修改优先级

嵌套

永远执行优先级高的中断 (例:在执行中断优先级低的中断程序B中,发生了一个更高优先级的中断请求C,那么则中断B,执行C,执行完成C后,在返回执行B)

定时器与中断

在这里插入图片描述

时钟系统,来一个脉冲,计数系统就+1

** 例子 !!!**

#include <REGX52.H>

unsigned char k;
unsigned short initValue;

/* how to skip interrupt code */
/*
 * 1 is interrput number
 * cpu use interrupt number to find interrupt code(interrupt server code)
 * no need to manual check TF0==1(while(TF0==0)), i.e. timer count number overflow!!!
 */
void timer0() interrupt 1
{
	/* setp5: reset init value */
	TH0=(unsigned char)((initValue>>8) & 0xFF);
	TL0=(unsigned char)(initValue & 0xFF); 
	TF0=0;
	k++;
}

void main()
{
	/* NOTE: variable must declare in block front*/
	unsigned char n,i;
	unsigned short timer_ms;
	n=0x01;
	k=0;
	
	/* !!! use interrupt method and config interrupt !!! */
	EA=1; // interrupt enable register,main flag
	ET0=1; // T0 timer interrupy enable flag
	
	/* setp1: config Timer register work mode */ 
  /* 0000 0001 -> T1(0000); T0(0001):: 
	 * GATE: 0 startup only with software
	 * C/T:  0 use to on timer 
	 * M1,M0: 0,1 : use TH0 and TL0
	 */
	TMOD=0x01;
	
	/* step2: set init value*/
	timer_ms=50; // 50ms
	initValue=65536-timer_ms*1000;
	TH0=(unsigned char)((initValue>>8) & 0xFF);
	TL0=(unsigned char)(initValue & 0xFF); 
	
	/* step3: start timer, if this timer is time out,the bit TF0 is 1*/
	TR0=1; // 0 is stop ; 1 is start (timer.start)
	
	while (1)
	{
		// left bit trans
		n=0x01;
		
		for (i=0;i<8;i++) // set 8 led 
		{
			P2=~n; // set led light
		
			/* !!! use variable k to connect timer0 function and contiol next code exec!!! */ 
			/* if timer time out k++, untill k=10 quit while code block */ 
			while (k<10) // 50ms *10 = 500ms is 0.5s
			{
//				/* setp4: wait timer time out*/	
//				while (TF0==0); // 
//				
//				/* setp5: reset init value */
//				TH0=(unsigned char)((initValue>>8) & 0xFF);
//				TL0=(unsigned char)(initValue & 0xFF); 
//				TF0=0;
//				k++;
			}
			
			// the next led
			k=0;
			n=n<<1;
		}	
		
	}
}

例子2

#include <REGX52.H>

unsigned short initValue=65535-1000; // 1ms; unsigned short initValue=65535-1000+1; // 1ms is +1 is best, counter!!!
unsigned int timer_xms=1000; // timer out control led switch

void initTimer0()
{
	/* timer contorl register */ 
	TMOD=0x01;
	
	/* interrupt overflow flag */ 
	TF0=0;

	/* timer0 start*/ 
	TR0=1;
	
	/* set timer count init value */
	TH0=((unsigned char)(initValue>>8))&0xFF; // 1000us=1ms 
	TL0=(unsigned char)(initValue&0xFF);
	
	/* set interrupt enable flag*/
	EA=1;
	ET0=1;
	PT0=0;
}

/* interrupt sub code */
void doTimer0() interrupt 1 // timer0 interrupt's number is 1
{
	static unsigned int timer_xms_count=0;
	timer_xms_count++;
	if (timer_xms_count==timer_xms)
	{
		P2_0=~P2_0;
		timer_xms_count=0;
	}
	
	/* set timer count init value */
	TH0=((unsigned char)(initValue>>8))&0xFF; // 1000us=1ms 
	TL0=(unsigned char)(initValue&0xFF);
}

void main()
{
	// init timer0
	initTimer0();
	
	// main code block
	while (1)
	{
		
	}
}

代码优化
TMOD=TMOD&0xF0; TMOD=TMOD|0x01; 代替 TMOD=0x01; 防止高四位被修改

外设例子

LED控制

#include <REGX52.H>
#include <INTRINS.H>

//void Delay500ms()		//@12.000MHz
//{
//	unsigned char data i, j, k;

//	_nop_();
//	i = 4;
//	j = 205; 	// 205
//	k = 187;	// 187
//	do
//	{
//		do
//		{
//			while (--k);
//		} while (--j);
//	} while (--i);
//}

void DelayXms(unsigned int xms)		//@12.000MHz
{
	unsigned char data i, j;
	
	unsigned int xms_num=0;
	while (xms_num++<xms)
	{
		i = 12;
		j = 169;
		do
		{
			while (--j);
		} while (--i);
	}
}


void main()
{
	unsigned char ledNum=0;
	while (1)
	{
		/* === exp1: led waterfall light === */
//		P2=0xFE;
//		DelayXms(100);
//		P2=0xFD;
//		DelayXms(200);
//		P2=0xFB;
//		DelayXms(300);
//		P2=0xF7;
//		DelayXms(500);
//		P2=0xEF;
//		DelayXms(500);
//		P2=0xDF;
//		DelayXms(600);
//		P2=0xBF;
//		DelayXms(700);
//		P2=0x7F;
//		DelayXms(800);
		
		/*******************************************************/
		/* === if key is down, the elec level is low level === */
		/*******************************************************/

		/* === exp2: key control led switch === */
		// down turn on, up turn off
//		if (P3_1==0) 	// read register
//		{
//			P2_0=0; 		// write register
//		}
//		else if (P3_1==1)
//		{
//			P2_0=1;			
//		}
		
		/* === exp3: key control led switch === */
		// key push once led switch once
//		if (P3_1==0)
//		{
//			DelayXms(20); 		// delay 20ms to filter 
//			while (P3_1==0);	// key up is turn off
//			DelayXms(20);			// delay 20ms to filter
//			P2_0=~P2_0;				// switch led
//		}
		
		/* === exp4: key control led switch === */
//		if (P3_1==0)
//		{
//			DelayXms(20); 		// delay 20ms to filter 
//			while (P3_1==0);	// key up is turn off
//			DelayXms(20);			// delay 20ms to filter
//			
//			ledNum++;
//			P2=~ledNum;
//		}

		/* === exp5: key control led switch === */
		if (P3_1==0)
		{
			DelayXms(20); 		// delay 20ms to filter 
			while (P3_1==0);	// key up is turn off
			DelayXms(20);			// delay 20ms to filter
			
			ledNum++;
			if (ledNum>=8)
			{
				ledNum=0;
			}
			P2=~(0x01<<ledNum);
		}
		
		/* === exp6: two key control led switch === */
		if (P3_1==0)
		{
			DelayXms(20); 		// delay 20ms to filter 
			while (P3_1==0);	// key up is turn off
			DelayXms(20);			// delay 20ms to filter
			
			ledNum++;
			if (ledNum>=8)
			{
				ledNum=0;
			}
			P2=~(0x01<<ledNum);
		}
		else if (P3_0==0)
		{
			DelayXms(20); 		// delay 20ms to filter 
			while (P3_0==0);	// key up is turn off
			DelayXms(20);			// delay 20ms to filter
			
			if (ledNum==0)
			{
				ledNum=7;
			}
			else
			{
				ledNum--;
			}
 
			P2=~(0x01<<ledNum);
		}
	}
}

数码管显示

// main.c
#include <REGX52.H>
#include "delay.h"
#include "ledControl.h"

//#define LED0 		0x3F 		// 0x3F 0B00111111
//#define LED1 		0x06		// 0x06 0B00000110
//#define LED2 		0x5B		// 0x5B 0B01011011
//#define LED3 		0x4F		// 0x4F 0B01001111
//#define LED4 		0x66		// 0x66	0B01100110
//#define LED5 		0x6D		// 0x6D 0B01101101
//#define LED6 		0x7D		// 0x7D 0B01111101
//#define LED7 		0x07		// 0x07 0B00000111
//#define LED8 		0x7F		// 0x7F 0B01111111
//#define LED9 		0x6F		// 0x6F 0B01101111
//#define LEDDOT 	0x80		// 0x67 0B10000000

//void DelayXms(unsigned int xms)		//@12.000MHz
//{
//	unsigned char data i, j;
//	
//	unsigned int xms_num=0;
//	while (xms_num++<xms)
//	{
//		i = 12;
//		j = 169;
//		do
//		{
//			while (--j);
//		} while (--i);
//	}
//}


//void ledDriverShowSwitch(bool isTurnOnAll)
//{
//	if (isTurnOnAll)
//	{
//		for (int i=0;i<8;i++)
//		{
//			
//		}
//	}
//}

//void ledDriverShow(unsigned char pos,unsigned char num)
//{
//	if (pos<0 || pos>7 )
//	{
//		return;
//	}
//	
//	if (num<0 || num >10)
//	{
//		return;
//	}
//	
//	// position
//	// pos use littleEnd
//	pos=7-pos;
//	P2_2=(pos) & 0x01;
//	P2_3=(pos>>1) & 0x01;	
//	P2_4=(pos>>2) & 0x01;
//	
//	// number
//	switch(num)
//	{
//		case 0:
//			P0=LED0;
//			break;
//		case 1:
//			P0=LED1;
//			break;
//		case 2:
//			P0=LED2;
//			break;
//		case 3:
//			P0=LED3;
//			break;
//		case 4:
//			P0=LED4;
//			break;
//		case 5:
//			P0=LED5;
//			break;		
//		case 6:
//			P0=LED6;
//			break;
//		case 7:
//			P0=LED7;
//			break;
//		case 8:
//			P0=LED8;
//			break;
//		case 9:
//			P0=LED9;
//			break;
//		default:
//			P0=LEDDOT;
//			break;
//	}
//	
//	// Prevent data misalignment
	DelayXms(1);
//	P0=0x00; // set zero to clear
//}

void main()
{
	/********************************************/
	/*** scan mode to update digit tube data ****/
	/********************************************/	
	
	/* === exp1: set digit led ,pos 3,num 6 === */
	//74HC138 decoder 
	// 0000 0101=5 set Y4(led6) on
//	P2_4=1;
//	P2_3=0;
//	P2_2=1;
//	
//	P0=0x7D; // set led digit tube: digit 6 
//	while(1)
//	{
//		
//	}
	
	/* === exp2: use function set digit led ,pos x,num y === */
	while (1)
	{
		int i=0;
		for (;i<8;i++)
		{
			ledDriverShow(i,i);
//			DelayXms(50);
		}
	}
}
// ledControl.h
#ifndef __LEDCONTROL_H__
#define __LEDCONTROL_H__

#include <REGX52.H>

#define LED0 		0x3F 		// 0x3F 0B00111111
#define LED1 		0x06		// 0x06 0B00000110
#define LED2 		0x5B		// 0x5B 0B01011011
#define LED3 		0x4F		// 0x4F 0B01001111
#define LED4 		0x66		// 0x66	0B01100110
#define LED5 		0x6D		// 0x6D 0B01101101
#define LED6 		0x7D		// 0x7D 0B01111101
#define LED7 		0x07		// 0x07 0B00000111
#define LED8 		0x7F		// 0x7F 0B01111111
#define LED9 		0x6F		// 0x6F 0B01101111
#define LEDDOT 	0x80		// 0x67 0B10000000

void ledDriverShow(unsigned char pos,unsigned char num);

#endif


// ledControl.c
#include "ledControl.h"

void ledDriverShow(unsigned char pos,unsigned char num)
{
	if (pos<0 || pos>7 )
	{
		return;
	}
	
	if (num<0 || num >10)
	{
		return;
	}
	
	// position
	// pos use littleEnd
	pos=7-pos;
	P2_2=(pos) & 0x01;
	P2_3=(pos>>1) & 0x01;	
	P2_4=(pos>>2) & 0x01;
	
	// number
	switch(num)
	{
		case 0:
			P0=LED0;
			break;
		case 1:
			P0=LED1;
			break;
		case 2:
			P0=LED2;
			break;
		case 3:
			P0=LED3;
			break;
		case 4:
			P0=LED4;
			break;
		case 5:
			P0=LED5;
			break;		
		case 6:
			P0=LED6;
			break;
		case 7:
			P0=LED7;
			break;
		case 8:
			P0=LED8;
			break;
		case 9:
			P0=LED9;
			break;
		default:
			P0=LEDDOT;
			break;
	}
	
	// Prevent data misalignment
	DelayXms(1);
	P0=0x00; // set zero to clear
}

按键

#ifndef __KEY_H__
#define __KEY_H__

#include <REGX52.H>
#include "delay.h"

unsigned char getKeyNumber();

#endif
// key.cpp
#include "key.h"

unsigned char getKeyNumber()
{
	unsigned char keyNumber=0;
	
	if (P3_1==0){DelayXms(20);while (P3_1==0);DelayXms(20);keyNumber=1;}
	if (P3_0==0){DelayXms(20);while (P3_0==0);DelayXms(20);keyNumber=2;}
	if (P3_2==0){DelayXms(20);while (P3_2==0);DelayXms(20);keyNumber=3;}
	if (P3_3==0){DelayXms(20);while (P3_3==0);DelayXms(20);keyNumber=4;}
	
	return keyNumber;
}

延时

代码

// delay.h
#ifndef __DELAY_H__
#define __DELAY_H__

void DelayXms(unsigned int xms);		//@12.000MHz

#endif
// delay.c
#include "delay.h"

void DelayXms(unsigned int xms)		//@12.000MHz
{
	unsigned char data i, j;
	
	unsigned int xms_num=0;
	while (xms_num++<xms)
	{
		i = 12;
		j = 169;
		do
		{
			while (--j);
		} while (--i);
	}
}

定时器 - 补充代码

代码1 配置定时器0和定时器1

#ifndef __MYTIMER_H__
#define __MYTIMER_H__

#include <REGX52.H>

void initTimer(unsigned char number,unsigned char mode,unsigned short initValue);
void setTimerInitValue(unsigned char number,unsigned short initValue);

#endif
// myTimer.c
#include "myTimer.h"

void initTimer(unsigned char number,unsigned char mode,unsigned short initValue)
{
	if (number==0) // timer 0
	{
		/* timer work mode register TMOD */
		TMOD=TMOD&0xF0;
		switch (mode)
		{
			case 1:
				TMOD=TMOD|0x01;	// 0000 0001
				break;
			case 2:
				TMOD=TMOD|0x02; // 0000 0010
				break;
			default:
				TMOD=TMOD|0x00;
				break;
		}
		
		/* timer control register TCON */
		/* interrupt overflow flag */ 
		TF0=0;
		
		setTimerInitValue(number,initValue);
		
		/* interrupt enable register IE*/
		/* set interrupt enable flag*/
		EA=1;
		ET0=1;
		PT0=0;
		
		/* timer0 start*/  // TCON
		TR0=1;
		

	}
	else if (number==1) // timer 1
	{
		/* timer work mode register TMOD */
		TMOD=TMOD&0xF0;
		switch (mode)
    {
    	case 1:
				TMOD=TMOD|0x10;	// 0001 0000
    		break;
    	case 2:
				TMOD=TMOD|0x20;	// 0010 0000
    		break;
    	default:
				TMOD=TMOD|0x00;
    		break;
    }
		
		/* timer control register TCON */
		/* interrupt overflow flag */ 
		TF1=0;
		
		setTimerInitValue(number,initValue);
		
		/* interrupt enable register IE*/
		/* set interrupt enable flag*/
		EA=1;
		ET1=1;
		PT0=0;
		
		/* timer0 start*/ 
		TR1=1;
	}
	
}

void setTimerInitValue(unsigned char number,unsigned short initValue)
{
	if (number==0)
	{
		/* set timer count init value */
		TH0=((unsigned char)(initValue>>8))&0xFF; // 1000us=1ms 
		TL0=(unsigned char)(initValue&0xFF);
	}
	else if (number==1)
	{
		/* set timer count init value */
		TH1=((unsigned char)(initValue>>8))&0xFF; // 1000us=1ms 
		TL1=(unsigned char)(initValue&0xFF);
	}
}

代码2 使用定时器的方法 查询按键是否被按下

ledControl.h 数码管

#ifndef __LEDCONTROL_H__
#define __LEDCONTROL_H__

#include <REGX52.H>

#define LED0 		0x3F 		// 0x3F 0B00111111
#define LED1 		0x06		// 0x06 0B00000110
#define LED2 		0x5B		// 0x5B 0B01011011
#define LED3 		0x4F		// 0x4F 0B01001111
#define LED4 		0x66		// 0x66	0B01100110
#define LED5 		0x6D		// 0x6D 0B01101101
#define LED6 		0x7D		// 0x7D 0B01111101
#define LED7 		0x07		// 0x07 0B00000111
#define LED8 		0x7F		// 0x7F 0B01111111
#define LED9 		0x6F		// 0x6F 0B01101111
#define LEDDOT 	0x80		// 0x67 0B10000000

void ledDriverShow(unsigned char pos,unsigned char num);

#endif

ledControl.c 数码管

#include "ledControl.h"
#include "delay.h"

void ledDriverShow(unsigned char pos,unsigned char num)
{
	if (pos<0 || pos>7 )
	{
		return;
	}
	
	if (num<0 || num >10)
	{
		return;
	}
	
	// position
	// pos use littleEnd
	pos=7-pos;
	P2_2=(pos) & 0x01;
	P2_3=(pos>>1) & 0x01;	
	P2_4=(pos>>2) & 0x01;
	
	// number
	switch(num)
	{
		case 0:
			P0=LED0;
			break;
		case 1:
			P0=LED1;
			break;
		case 2:
			P0=LED2;
			break;
		case 3:
			P0=LED3;
			break;
		case 4:
			P0=LED4;
			break;
		case 5:
			P0=LED5;
			break;		
		case 6:
			P0=LED6;
			break;
		case 7:
			P0=LED7;
			break;
		case 8:
			P0=LED8;
			break;
		case 9:
			P0=LED9;
			break;
		default:
			P0=LEDDOT;
			break;
	}
	
	// Prevent data misalignment
	DelayXms(1);
	P0=0x00; // set zero to clear
}

key.h

#ifndef __KEY_H__
#define __KEY_H__

#include <REGX52.H>
#include "delay.h"

unsigned char getKeyNumber();
unsigned char getKeyState();
void keyInterruptLoop();
unsigned char getFinalKeyNumber();

#endif

key.c

#include "key.h"

static unsigned char keyNumber_finalget=0;

unsigned char getKeyNumber()
{
	unsigned char keyNumber=0;
	
	if (P3_1==0){DelayXms(20);while (P3_1==0);DelayXms(20);keyNumber=1;}
	if (P3_0==0){DelayXms(20);while (P3_0==0);DelayXms(20);keyNumber=2;}
	if (P3_2==0){DelayXms(20);while (P3_2==0);DelayXms(20);keyNumber=3;}
	if (P3_3==0){DelayXms(20);while (P3_3==0);DelayXms(20);keyNumber=4;}
	
	return keyNumber;
}

unsigned char getKeyState()
{
	unsigned char keyNumber=0;
	
	if (P3_1==0){keyNumber=1;}
	if (P3_0==0){keyNumber=2;}
	if (P3_2==0){keyNumber=3;}
	if (P3_3==0){keyNumber=4;}
	
	return keyNumber;
}

void keyInterruptLoop()
{

	static unsigned char prekeyState=0;
	static unsigned char currkeyState=0;
	
	prekeyState=currkeyState;
	currkeyState=getKeyState();
	
	// think more
	// noly check release or not, i.e. from press to release
	if (prekeyState==1 && currkeyState==0)
	{
		keyNumber_finalget=1;
	}
	else	if (prekeyState==2 && currkeyState==0)
	{
		keyNumber_finalget=2;
	}
	else	if (prekeyState==3 && currkeyState==0)
	{
		keyNumber_finalget=3;
	}
	else	if (prekeyState==4 && currkeyState==0)
	{
		keyNumber_finalget=4;
	}
}

unsigned char getFinalKeyNumber()
{
	unsigned char keyNumber_temp=0;
	keyNumber_temp=keyNumber_finalget;
	keyNumber_finalget=0; // clear; keep keyNumber_finalget is 0;
	return keyNumber_temp;
}

main.c

#include <REGX52.H>
#include "delay.h"
#include "key.h"
#include "AT24C02.h"
#include "myTimer.h"
#include "ledControl.h" // 数码管

unsigned short initValue=65536-1000; // 1000us=1ms
unsigned int timer_xms=1000; // 1000*1ms=1s
unsigned int key_timer_xms=20; // 20*1ms=20ms

unsigned char keyNumber=0;
unsigned char keyNumberToShow=0;

void timer0_interrupt() interrupt 1
{
	static unsigned int timer_xms_count=0;
	timer_xms_count++;
	
	if (timer_xms_count==key_timer_xms)
	{
		timer_xms_count=0;
		keyInterruptLoop();
	}
	
	setTimerInitValue(0,initValue);
}

void main()
{
	initTimer(0,initValue);
	while (1)
	{
		keyNumber=getFinalKeyNumber();
		if (keyNumber)
		{
			keyNumberToShow=keyNumber;
		}
		ledDriverShow(0,keyNumberToShow);
	}
}

AD/DA

https://www.bilibili.com/video/BV1BV4y1V7nE/?spm_id_from=333.999.0.0&vd_source=7155082256127a432d5ed516a6423e20

运算放大器

https://www.bilibili.com/video/BV1n44y1Q7We/?spm_id_from=333.337.search-card.all.click&vd_source=7155082256127a432d5ed516a6423e20

https://www.bilibili.com/video/BV12D4y1h7qz/?spm_id_from=333.999.0.0&vd_source=7155082256127a432d5ed516a6423e20

ADC

https://www.bilibili.com/video/BV1rL411U77J/?spm_id_from=333.337.search-card.all.click&vd_source=7155082256127a432d5ed516a6423e20

看门狗

watch dog timer 本质是一个定时器

定时器
在这里插入图片描述

看门狗

时间到了,触发的不是中断函数,而是触发的单片机复位
预先设置一个时间,时间到了就重启

使用

没死机就喂狗,死机了(到达时间了 看门狗就直接复位)
如果到达时间不喂狗,那么到了时间就复位(高频复位就变成了疯狗)
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值