易失性存储器:掉电丢失数据
存取速度快
非易失性存储器:掉电不丢失数据
存取速度慢
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
#include
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
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
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;
防止高四位被修改
#include
#include
//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<
}
/* === 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
#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++
// {
// 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
#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
#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);
}
}
#ifndef __MYTIMER_H__
#define __MYTIMER_H__
#include
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);
}
}
ledControl.h 数码管
#ifndef __LEDCONTROL_H__
#define __LEDCONTROL_H__
#include
#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
#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
#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);
}
}