一、外部中断
外部中断0(INT0)和外部中断1(INT1)分别有上升沿或下降沿触发方式,和仅下降沿触发方式。
题目:
代码:
#include <STC15F2K60S2.H>
sbit L1 = P0^0;
sbit L8 = P0^7;
void InitHC138()
{
P2 = (P2 & 0x1f)| 0x80;
}
void Delay(unsigned int n)
{
while(n--);
}
void working()
{
L1 = 0;
Delay(60000);
L1 = 1;
Delay(60000);
}
void INT0_Init()
{
IT0 = 0;
EX0 = 1;
EA = 1;
}
unsigned char flag = 0;
void INT0Service() interrupt 0
{
//直接在中断中让灯反转
// L8 = 0;
// Delay(60000);
// Delay(60000);
// Delay(60000);
// Delay(60000);
// L8 = 1;
//通过标志位
flag = 1;
}
void LEDINT()
{
if(flag == 1)
{
L8 = 0;
Delay(60000);
Delay(60000);
Delay(60000);
L8 = 1;
}
flag = 0;
}
void main()
{
InitHC138();
INT0_Init();
while(1)
{
working();
LEDINT();
}
}
二、定时器
题目:
代码:
#include <STC15F2K60S2.H>
sbit L1 = P0^0;
sbit L8 = P0^7;
void InitHC138()
{
P2 = (P2 & 0x1f) | 0x80;
}
void Timer0_Init()
{
TMOD = 0x01;
TH0 = (65535-50000)/256;
TL0 = (65535-50000)%256;
TR0 = 1;
ET0 = 1;
EA = 1;
}
unsigned char count = 0;
void ServiceTimer0() interrupt 1
{
TH0 = (65535-50000)/256;//16位不可重装,需要在中断中手动重装。
TL0 = (65535-50000)%256;
count++;
if (count%10 == 0)
{
L1 = ~L1;
}
if(count == 100)
{
L8 = ~L8;
count = 0;
}
}
void main()
{
Timer0_Init();
InitHC138();
while(1)
{
}
}
三、定时器进阶
问题:
代码:
#include <STC15F2K60S2.H>
unsigned char T_min = 0;
unsigned char T_sec = 0;
unsigned char T_msec = 0;
sbit S4 = P3^3;
sbit S5 = P3^2;
unsigned char code SMG_duanma[18] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xbf,0x7f};
void Delay(unsigned int t)
{
while(t--);
}
void HC138_Init(unsigned char n)
{
switch(n)
{
case 7:
P2 = (P2 & 0x1f) | 0xe0;
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0;
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0;
break;
case 4:
P2 = (P2 & 0x1f) | 0x80;
break;
case 3:
P2 = (P2 & 0x1f) | 0x60;
break;
case 2:
P2 = (P2 & 0x1f) | 0x40;
break;
case 1:
P2 = (P2 & 0x1f) | 0x20;
break;
}
}
void Shumaguan_show(unsigned char dat,unsigned char pos)//pos:0-7
{
HC138_Init(6);
P0 = 0x01<<pos;
HC138_Init(7);
P0 = SMG_duanma[dat];
}
void Scan_key()
{
if(S4 == 0)
{
Delay(100);
if(S4 == 0)
{
TR0 = ~ TR0;
}
while(S4 == 0);//等待按键松开,加入这句不会出现按键识别不到等现象
}
if(S5 == 0)
{
Delay(100);
if(S5 == 0)
{
T_min = 0;
T_sec = 0;
T_msec = 0;
}
while(S5 == 0);
}
}
void Time_show()
{
Shumaguan_show(T_msec%10,7);
Delay(500);
Shumaguan_show(T_msec/10,6);
Delay(500);
Shumaguan_show(16,5);
Delay(500);
Shumaguan_show(T_sec%10,4);
Delay(500);
Shumaguan_show(T_sec/10,3);
Delay(500);
Shumaguan_show(16,2);
Delay(500);
Shumaguan_show(T_min%10,1);
Delay(500);
Shumaguan_show(T_min/10,0);
Delay(500);
}
void Timer0_Init()
{
TMOD = 0x01;
TH0 = (65535-50000)/256;
TL0 = (65535-50000)%256;
TR0 = 1;
ET0 = 1;
EA = 1;
}
void Timer0Service() interrupt 1
{
TH0 = (65535-50000)/256;
TL0 = (65535-50000)%256;
T_msec++;
if(T_msec == 20)
{
T_msec=0;
T_sec++;
if(T_sec == 60)
{
T_sec = 0;
T_min++;
}
if(T_min == 99)
{
T_min = 0;
}
}
}
void main()
{
Timer0_Init();
while(1)
{
Time_show();
Scan_key();
// Shumaguan_show(1,1);
// Delay(300);
}
}
TR0寄存器用来控制定时器的运行,TR0 = 1时定时器允许运行,TR0 = 0时定时器禁止运行。
四、PWM
问题:
思路:
100HZ,对应的周期就是10ms ,10ms = 100us*100;定时器设置100us产生一次中断并计数,设置灯的状态位,当计数值小于设定值改变对应灯的状态位。
代码:
#include <STC15F2K60S2.H>
sbit L1 = P0^0;
sbit S7 = P3^0;
void HC138_Init()
{
P2 =(P2 & 0x1f)| 0x80;
}
void Timer0_Init()
{
TMOD = 0x01;
TH0 = (65535-100)/256;
TL0 = (65535-100)%256;
ET0 =1;
EA = 1;
}
void Delay(unsigned char t)
{
while(t--);
}
unsigned char state = 0;unsigned char count = 0 ;unsigned char pwm_duty = 0;
void KEY_Scan()
{
if(S7 == 0)
{
Delay(100);
if(S7 == 0)
{
switch(state)
{
case 0:
TR0 = 0;
state =1;
L1 = 1;
break;
case 1:
TR0 = 1;
L1 = 0;
state = 2;
pwm_duty = 10;
break;
case 2:
state = 3;
pwm_duty = 50;
break;
case 3:
state = 0;
pwm_duty = 90;
break;
}
}
while(S7 == 0);
}
}
void Timer0_Service() interrupt 1
{
TH0 = (65535-100)/256;
TL0 = (65535-100)%256;
count++;
if(count == pwm_duty)
{
L1 = 1;
}
else if(count == 100)
{
count = 0;
L1 = 0;
}
}
void main()
{
HC138_Init();
Timer0_Init();
while(1)
{
KEY_Scan();
}
}
五、串口
并行通信:数据的各位同时发送和接受,每个位使用一根导线。
串行通信:数据一位接一位地发送或接受。
同步串行通信:需要使用同一个时钟,以数据块为单位传输数据。
异步串行通信:每个设备都有自己的时钟信号,通信中双方的波特率要保持一致,以字符为单位进行数据帧传输。
问题1:
代码:
#include <STC15F2K60S2.H>
unsigned char date;
void UART_Init()
{
TMOD = 0x20;
TH1 = 0xfd;
TL1 = 0xfd;
TR1 = 1;
SCON = 0x50;
AUXR = 0x00;//必须开启辅助寄存器
ES = 1;
EA = 1;
}
void Send_Byte(unsigned char dat)
{
SBUF = dat;
while(TI == 0);
TI = 1;
}
void AURT_Service() interrupt 4
{
if(RI == 1)
{
RI = 0;
date = SBUF;
Send_Byte(date+1);
}
}
void main()
{
UART_Init();
Send_Byte(0x5a);
Send_Byte(0xa5);
while(1)
{
}
}
问题2:
代码:
#include <STC15F2K60S2.H>
unsigned char date = 0 ;
void HC138_Init(unsigned char n)
{
switch(n)
{
case 7:
P2 = (P2 & 0x1f) | 0xe0;
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0;
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0;
break;
case 4:
P2 = (P2 & 0x1f) | 0x80;
break;
case 3:
P2 = (P2 & 0x1f) | 0x60;
break;
case 2:
P2 = (P2 & 0x1f) | 0x40;
break;
case 1:
P2 = (P2 & 0x1f) | 0x20;
break;
}
}
void UART_Init()
{
TMOD = 0x20;
TH1 = 0xfd;
TL1 = 0xfd;
TR1 = 1;
SCON = 0x50;
AUXR = 0x00;
ES = 1;
EA = 1;
}
void Send_Byte(unsigned char byte)
{
SBUF = byte;
while(TI==0);
TI = 0;
}
void Send_str(unsigned char *str)
{
while(*str!='\0')
{
Send_Byte(*str++);
}
}
void UART_Service() interrupt 4
{
if(RI == 1)
{
RI = 0;
date = SBUF;
}
}
void System_Init()
{
HC138_Init(5);
P0 = 0x00;
HC138_Init(4);
P0 = 0xff;
Send_str("Welcome to XMF system!\r\n");
}
void working()
{
if(date != 0x00)
{
switch(date & 0xf0)
{
case 0xa0:
P0 = (P0 | 0x0f) & (~date | 0xf0);
break;
case 0xb0:
P0 = (P0 | 0xf0) & (~date<<4 | 0x0f);
break;
case 0xc0:
Send_str("The System is Running...\r\n");
date = 0x00;
break;
}
}
}
void main()
{
UART_Init();
System_Init();
while(1)
{
working();
}
}
P0 = (P0 | 0x0f) & (~date | 0xf0); P0 =(P0 | t)&(date | a) t一个字节,需要改变的位置0,不需要改变的位置1。a是t的取反。这个方法可以实现对一个字节中位操作。
六、存储器映射扩展
问题:
使用存储器映射的方式的时候,需要将单片机接到MM模式。
代码:
#include <STC15F2K60S2.H>
#include "absacc.h"//使用存储器映射的方式,必须包括这个头文件
void Delay(unsigned int t)
{
while(t--);
while(t--);
}
void working()
{
unsigned char i = 0;
XBYTE[0x8000] = 0xf0;
Delay(60000);
Delay(60000);
XBYTE[0x8000] = 0x0f;
Delay(60000);
Delay(60000);
XBYTE[0x8000] = 0xff;
for(i = 0;i<8;i++)
{
XBYTE[0xc000] = 0x01<<i;
XBYTE[0xe000] = 0x00;
Delay(60000);
Delay(60000);
XBYTE[0xe000] = 0xff;
}
}
void main()
{
while(1)
{
working();
}
}
七、综合应用
问题:
代码:
#include <STC15F2K60S2.H>
unsigned char T_sec = 0;
unsigned char T_min = 0;
unsigned char T_hour = 0;
unsigned char count = 0;
unsigned char SMG[18]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xbf,0x7f};
unsigned char rec = 0;
unsigned char command = 0;
unsigned char light = 0xf0;
sbit S4 = P3^3;
sbit S5 = P3^2;
void HC138_Init(unsigned char n)
{
switch(n)
{
case 7:
P2 = (P2 & 0x1f) | 0xe0;
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0;
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0;
break;
case 4:
P2 = (P2 & 0x1f) | 0x80;
break;
case 3:
P2 = (P2 & 0x1f) | 0x60;
break;
case 2:
P2 = (P2 & 0x1f) | 0x40;
break;
case 1:
P2 = (P2 & 0x1f) | 0x20;
break;
}
}
void System_Init()
{
HC138_Init(5);
P0 = 0x00;
}
void Delay(unsigned int t)
{
while(t--);
while(t--);
}
void LED_Check()
{
unsigned char i = 0;
for(i=0;i<8;i++)
{
HC138_Init(4);
P0 = 0xFE<<i;
Delay(60000);
}
P0 = 0x00;
for(i=0;i<8;i++)
{
P0 = P0 |(0x01<<i);
Delay(60000);
}
}
void SMG_Check()
{
unsigned char j = 0,k=0;unsigned char date = 0x00;
for(j=0;j<8;j++)
{
HC138_Init(6);
// P0 =date|(0x01<<j);
// date = P0;
P0 =~(0xfe<<j);
HC138_Init(7);
P0 = 0x00;
Delay(60000);
}
for(k=0;k<8;k++)
{
HC138_Init(6);
P0 = 0xfe <<k;
Delay(60000);
Delay(60000);
}
}
void Timer_Init()
{
TMOD = 0x21;
TH0 = (65535-50000)/256;
TL0 = (65535-50000)%256;
TR0 = 1;
ET0 = 1;
EA = 1;
}
void Timer0_Service() interrupt 1
{
count++;
if(count == 20)
{
count=0;
T_sec++;
if(T_sec == 60)
{
T_sec = 0;
T_min++;
if(T_min == 60)
{
T_min = 0;
T_hour++;
}
}
if(T_hour == 99)
{
T_hour = 0;
}
}
}
void UART_Init()
{
TMOD = 0x21;
TH1 = 0xfd;
TL1 = 0xfd;
TR1 = 1;
SCON = 0x50;
AUXR = 0x00;
ES = 1;
EA = 1;
}
void UART_Service() interrupt 4
{
if(RI)
{
RI = 0;
command = SBUF;
}
}
void Send_Byte(unsigned char byte)
{
SBUF = byte;
while(TI == 0);
TI = 0;
}
void Send_str(unsigned char *str)
{
while(*str != '\0')
{
Send_Byte(*str++);
}
}
void SMG_show(unsigned char n,unsigned char pos)
{
HC138_Init(6);
P0 = 0x01<<pos;
HC138_Init(7);
P0 = SMG[n];
}
void SMG_Delay(unsigned int t)
{
while(t--);
}
void SMG_showtime()
{
SMG_show(T_sec%10,7);
SMG_Delay(100);
SMG_show(T_sec/10,6);
SMG_Delay(100);
SMG_show(16,5);
SMG_Delay(100);
SMG_show(T_min%10,4);
SMG_Delay(100);
SMG_show(T_min/10,3);
SMG_Delay(100);
SMG_show(16,2);
SMG_Delay(100);
SMG_show(T_hour%10,1);
SMG_Delay(100);
SMG_show(T_hour/10,0);
SMG_Delay(100);
}
void Get_BCD(unsigned char hour,unsigned char min,unsigned char sec)
{
Send_Byte((hour/10)<<4|(hour%10));
Send_Byte((min/10)<<4|(min%10));
Send_Byte((sec/10)<<4|(sec%10));
}
void UART_working()
{
if(command!= 0)
{ switch(command & 0xf0)
{
case 0xa0:
HC138_Init(4);
P0 = (light | 0x0f) & (~command | 0xf0);
light = P0;
break;
case 0xb0:
Get_BCD(T_hour,T_min,T_sec);
command = 0x00;
break;
}
}
}
void KEY_Scan()
{
if(S4 == 0)
{
SMG_Delay(100);
while(S4 == 0)
{
SMG_showtime();
}
HC138_Init(4);
light = (light|0x80)&(~light|0x7f);
P0 = light;
}
if(S5 == 0)
{
SMG_Delay(100);
while(S5 == 0)
{
SMG_showtime();
}
HC138_Init(4);
light = (light|0x40)&(~light|0xbf);
P0 = light;
}
}
void main()
{
System_Init();
LED_Check();
SMG_Check();
Timer_Init();
UART_Init();
while(1)
{
SMG_showtime();
UART_working();
KEY_Scan();
}
}