git test message

  • Information & Data sheet

Based on –AT89C51.

The Atmel AT89 series is an Intel 8051-compatible family of 8 bit microcontrollers (μCs) manufactured by the Atmel Corporation.

Based on the Intel 8051 core, the AT89 series remains very popular as general purpose microcontrollers, due to their industry standard instruction set, their low unit cost, and the availability of these chips in DIL (DIP) packages. This allows a great amount of legacy code to be reused without modification in new applications. While less powerful than the newer AT90 series of AVR RISC microcontrollers, new product development has continued with the AT89 series for the aforementioned advantages.

More recently, the AT89 series has been augmented with 8051-cored special function microcontrollers, specifically in the areas of USB, I²C (two wire interface), SPI and CAN bus controllers, MP3 decoders and hardware PWM.

Data sheet url links : Data Sheet PDF Downloads

features of AT89C51

The following I would not like to just write down the points. The post will be focused on application layer

Project_1_1:TIME BOMB

​ It’s actually very easy to make a TIME BOMB than you can imagine.You will just need some TNT and an at89c51 chip(<3).

Now that we fixed the Bomb (got some TNT). What about the timer ? Yep, we can use the AT89C51 chip.

Timer

1
2
3
4
5
6
void delayN10ms(unsigned int N){
unsigned int i;
for(N;N>0;N--)
for(i=1275;i>0;i--); //different types of chips have different delay functions
//and it's also related to the crystal oscillator
}

what about the next to do after the timer is set? yep , light it.

We can use a switch or a relay to light it . When the switch (connected between vcc and gnd) is on , the heat will light the TNT. EZ game.

1
2
3
4
5
6
7
8
9
10
11
12
void delayN10ms(unsigned int N){
unsigned int i;
for(N;N>0;N--)
for(i=1275;i>0;i--); //different types of chips have different delay functions
//and it's also related to the crystal oscillator
}

void main()
{
delayN10ms(10000);//10s
P1=0x00;
}

 schematic

project_1_2 : CANCEL the TIME BOMB

​ Now that we create a time bomb , we are going to use it to rob a bank . However your

incompetent teammates set the bomb early! You guys are to be exposed to TNT in just 10s . What are you going to do ?

  • Yes ,for sure you can reset the chip.
  • Also we can use a technique called INTERRUPTION

Now we are going to talk about INTERRUPTION

The chip AT89C51 has six interrupt sources .

What is an interrupt ?

An interrupt is an external or internal event to get the CPU’s attention. Once the controller detects the interrupt, it suspends the current job and executes a special service routine know as Interrupt Service Routine(ISR).

Upon activation of an interrupt, the microcontroller goes through the following steps

  1. First it finishes the instruction it is executing and saves the address of the next instruction (PC) on the stack.

  2. It also saves the current status of all the interrupts internally.

  3. It jumps to a fixed location in memory, called the interrupt vector table, that holds the address of the ISR. The microcontroller gets the address of the ISR from the interrupt vector table and jumps to it It starts to execute the interrupt service subroutine until it reaches the last instruction of the subroutine which is RETI (return from interrupt)

  4. Upon executing the RETI instruction, the microcontroller returns to the place where it was interrupted.

  5. First, it gets the program counter (PC) address from the stack by popping the top two bytes of the stack into the PC.

  6. Then it starts to execute from that address.

    information from here

8051 interrupt Structure

8051 Microcontroller has six interrupt sources as shown in the table below:

Interrupt ROM Location(Hex) Pin Flag Clearing Interrupt no. in C
Reset 0000 9 Auto
External HW Interrupt 0 (INT0) 0003 P3.2(12) Auto 0
Timer 0 Interrupt(TF0) 000B - Auto 1
External HW Interrupt 1 (INT1) 0013 P3.3(13) Auto 2
Timer 1 Interrupt(TF1) 001B - Auto 3
Serial Com Interrupt(RI and TI) 0023 - Program SW 4
  • the reset vector has just 3 bytes allocated to it, meaning it can hold a jump instruction to the location where the main program is stored.
  • The other interrupts have 8 bytes allocated to each of them, hence a small Interrupt service routine(ISR) can be placed here. However, if the ISR needs to larger in length, it has to placed else where and the allocated 8 bytes need to have the code that simple redirects the control to the ISR.
  • INT0 and INT1 are external interrupts on P3.2 and P3.3 respectively. These can be configured to be low level triggered or edge triggered interrupt sources.
  • TF0 and TF1 are timer overflow interrupts for timer 0 and 1 respectively
  • The Serial COM Interrupt can be configured to trigger upon transmit or receipt of a byte during serial communication.

enable interruption

structure of 51 interrupt

**example code using external interrupt **

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void setUp(){
IP = 0x04;
EA=1;
EX0=1; // allow external interrupt INT0
IT0 = 1; // set edge triggerin
}
void main(void){
setUp();
delayNms(10000);//10s
P1=0x00; //start BOMB
}
void int0(void) interrupt 0{

P1=0xff; //cancel the timer
P2=0x00; //to display
delayN10ms(1000); // pause 10s for your survive
P2=0xff; //to display
}

simple example

Now you can run away safely ;D.

**The above codes are just some rough examples . **

Project_1_3 : the final version of the time bomb

First , we are going to design the schematic seriously.

the final schematic

codes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include<reg51.h>

sbit button_1=P2^4;

void delayNms(int N) //@11.0592MHz
{
unsigned char i;

while(N){
for(i=1275;i>0;i--);
N--;
}
}

void bombStart();


void main(){

//setup
IP = 0x04;
EA=1;
EX0=1; // allow external interrupt INT0
IT0 = 1; // set edge triggering
P2 =0xff;
while(1){
if(button_1==0){
bombStart();
}
}
}

void bombStart(){
delayNms(10000);
P1=0x00;
}
void int0(void) interrupt 0{

P1=0xff;//cancel the timer
delayNms(10000); // increase 10s for your survive
}

explanations:

  1. Once the bomb is set up , you need to press the start button to start the bomb.
  2. Once you start the bomb , you have 10 s to run away .
  3. If you want to delay the bomb , press the button “PAUSE” .
    • ps: there is no way you can cancel the bomb unless you reset or cut off the power .

other information

1
2
3
4
5
6
7
IT1 = 1; // Enable external interrupt 1 to trigger by a falling edge signal. 

IT1 = 0; // Enable a low level signal on external interrupt 1 to generate an interrupt.

IT0 = 1; // Enable external interrupt 0 to trigger by a falling edge signal.

IT0 = 0; // Enable a low level signal on external interrupt 1 to generate an interrupt.

Project_1_4: Use a TIMER interrupt to set the bomb

​ To control the timer and specify our needs/logic we have to configure the timers first. For configuring and controlling the 89c51 microcontroller timers we have four registers. These registers are associated with timers of 89c51 micro controller. Each register plays an important role in controlling and configuring the timer.

**Registers that are associated with timers. **

-

  • (Timer Control register)
  • TMOD (Timer Mode register)
  • TH0/TL0 (Timer 0, 16-bit register, High bits goes to TH0, Low bits goes to TL0)
  • TH1/TL1 (Timer 1, 16-bit register, High bits goes to TH1, Low bits goes to TL1)

Formula if TIMER INTERRUPT

TH0/TL0(Timer-0) = TH1/TL1(Timer-1)

These two registers TH and TL are timer high byte and timer low byte registers. 0 and 1 are the timers numbers. These are 16-bit registers. we Load our time delays/counter value in these registers. Recall 8051 timer counter can count up to 65535 and 16 bits cover 65535 in binary. Since 8051(89c51,89c52) is an 8-bit microcontroller, so to load 65535 we need two registers one representing the high byte and other the low byte. we access these register in two bytes one byte for TH(timer high byte) and TL(timer low byte). TH and TL together makes 16-bits(TH 8-bit, TL8-bit). TH0 and TL0 are byte addressable only.

  • how to set them then ? There is an example .

Calculating Delay for 8051(89c51,89c52) microcontroller

TCON(Timer control) Register of 8051 Microcontroller

TCON(Timer Control) is an 8-bit register. It’s bits are used for generating interrupts on gpio pins internal or external. The most important bits of the timers TRx and TFx are also in it. TRx(timer run) and TFx(timer overflow) bits which we use in almost all our timer applications are in it. When we initialize TRx with 1, TRx=1 it means start the timer, When the specified time is over the timer it self make TFx=1 which means that the delay value is reached. Once TFx=1 stop the timer by initializing TRx with 0 TRx=0(Stop Timer). Now if we again want to run the timer make TRx=1. In the diagram you can see the SFR for TCON register, the bit’s used for interrupt handling and the timer run and timer over flow bits. If you want to access the individual bits of the registers, you can access them by their names. You can also access whole register it self by its name. At the bottom of the page their is a small example explaining it.

Now we are going to upgrade our Bomb!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <REGX52.H>

sbit led=P2^4;

int cnt=0;

void Time0Init(void)
{
//配置定时器0工作模式16位计时
//set T0 working mode with 16 bits
TMOD&=0xF0;
TMOD|=0x01;
//给初值,定制10ms
//set initial value , create 10 ms delay
TL0=0x00;
TH0=0xDC;

TR0=1;//开始计时
// turn on T0
TF0=0;

//打开定时器0中断
//turn on T0 interrupt
ET0=1;
//打开总中断
// turn on general interrupt
EA=1;
}

void main()
{

led=1;

Time0Init();

while(1)
{
;//do noting
}
}

void Time0Rountime() interrupt 1
{
cnt++; //cnt++用来记录第一次爆表,cnt是1次
// record the interrupt times
//重新给初值
//reset the initial value
TL0=0x00;
TH0=0xDC;
if(cnt==1000) //爆表100次,经过10s,led就亮
// after 100 times which the time passes 1s
{
cnt=0; //当1s时,让count从0开始,计算下一次的1s
// set the cnt again
P1=0x00; //BOMb!!!
}
}

1. What if we get many BOMBs which they are set at different palces ?

  • Explode with a delay ( such as 1 s )

Solution KEY :

​ Once the first BOMB is about to explode , it sends a signal to another BOMB.

the signal :

  1. Voltage (like 0 v —> 1 v or reverse it )
  2. Waves of Voltage ( PULSE )
  3. Serial text

1. Voltage

​ Once the first bomb is about to explode, it sends a Voltage signal to the second and so on.

​ We can use one of a pin to do this work .

  • The first BOMB
1
2
3
4
5
6
7
void main()
{

delayN10ms(10000); //10s
P2.1=0; // send a signal ( 5v )
P1=0x00;
}
  • The second BOMB
1
2
3
4
5
6
7
8
9
10
void main()
{
while(1){
if(P2.1==0){
delayN10ms(10000); //10s
P2.2=0; // send a signal to the third BOMB (send to P2.1) ( 5v )
P1=0x00;
}
}
}

2. Through Plain Text(by serial )

The procedure :

  1. Set the first bomb
  2. Connect to the the second Bomb and the third one so on
  3. Start the first Bomb
  4. the second before the first Bomb is about to explode ,it send a message “BOMB”

The schematic

the final version

The first BOMB.

  • Transmit signal ( We only use the send module, so we just need one pin ( TX ))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <reg51.h>

unsigned char seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //数码管驱动

sbit start = P1^7;
sbit bomb = P1^0;

int timeS=9;
void delayNms(int N) // @11.0592MHz 延时函数
{
unsigned char i;

while(N){
for(i=1275;i>0;i--);
N--;
}
}
void serialInit(){

TH1=0xFD; //Set timer 1 for BAUD=9600
TMOD=0x20; //Set Timer 1 in Mode 2 8-bit Auto reload
SCON=0x50; //Set serial reception enable and Mode 1 8-bit UART
TR1=1; //Start Timer 1

}
void interruptSetUp(){
IP = 0x04;
EA = 1;
EX0 = 1; // allow external interrupt INT0
EX1 = 1;
IT0 = 1; // set edge triggerin
IT1 = 1;
}
void sendSignal(){
unsigned char Message[15]={"BOMB"};
char i;
delayNms(300);
for (i=0;i<7;i++)
{
SBUF = Message[i]; //Send one by one each byte to serial
while(TI==0); //Wait for Transmition complition
TI=0; //Clear Transmit Intterupt flag
}

}
void main()
{
serialInit();// initialize
interruptSetUp();
while(1){

if(start==0){
timeS=9;
while(1){

P0=seg[timeS];
delayNms(500);
timeS--;
if(timeS==-1){
sendSignal();
delayNms(10);
bomb=0;
while(1);
}
}
}

}


}

void int0(void) interrupt 0{ // stop all the BOMBs entirely
while(1){

}
}
void int1(void) interrupt 2{
delayNms(5000); //pause for 5 seconds
}

The second BOMB

  • Receive the signal from the last BOMB
  • Transmit signal to the third
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <REGX52.H>

unsigned char seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //数码管驱动
unsigned char Message[15]={"BOMB"};
unsigned char receivedMessage[15];
unsigned int r=0;
int timeS=9;
sbit bomb = P1^0;

void delayNms(int N) //@11.0592MHz 延时函数
{
unsigned char i;

while(N){
for(i=1275;i>0;i--);
N--;
}
}
void interruptSetUp(){
IP = 0x04;
EA = 1;
EX0 = 1; // allow external interrupt INT0
EX1 = 1;
IT0 = 1; // set edge triggerin
IT1 = 1;
}

void UartInit() //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //设定定时器1为8位自动重装方式
TL1 = 0xFD; //设定定时初值
TH1 = 0xFD; //设定定时器重装值
TR1 = 1; //启动定时器1
ET1 = 0; //禁止定时器1中断
EA=1; //开放总中断
ES=1; //开放串口中断

}
void Uartsend(unsigned char byte)//发送
{
receivedMessage[r]=byte;//把数据写入发送缓冲区SBUF
r++;
}
void sendSignal(){
char i;
delayNms(300);
for (i=0;i<7;i++)
{
SBUF = Message[i]; //Send one by one each byte to serial
while(TI==0); //Wait for Transmition complition
TI=0; //Clear Transmit Intterupt flag
}

}
void sendReceivedSignal(){
char i;
delayNms(300);
for (i=0;i<r;i++)
{
SBUF = receivedMessage[i]; //Send one by one each byte to serial
while(TI==0); //Wait for Transmition complition
TI=0; //Clear Transmit Intterupt flag
}

}
void UART_ISR() interrupt 4 //串口中断函数
{
if(RI==1)//接收中断
{
Uartsend(SBUF);//把接收的数据发送到计算机
RI=0;//软件清零
}
}
int compareMessage(){
if(receivedMessage[0]=='B'&&receivedMessage[1]=='O'&&receivedMessage[2]=='M'&&receivedMessage[3]=='B')
return 1;
else{
return 0;
}
}
int main()
{
UartInit();
interruptSetUp();

while(1)
{

if(compareMessage()==1){
while(1){

P0=seg[timeS];
delayNms(500);
timeS--;
if(timeS==-1){
sendSignal();
delayNms(10);
bomb=0;
while(1);
}
}
}

}
}

void int0(void) interrupt 0{
while(1){

}
}
void int1(void) interrupt 2{
delayNms(5000);
}

The THird BOMB.

Actually it does the same thing as the second one .

  • Receive the signal from the last BOMB
  • Transmit signal to the third one
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <REGX52.H>

unsigned char seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //数码管驱动
unsigned char Message[15]={"BOMB"};
unsigned char receivedMessage[15];
unsigned int r=0;
int timeS=9;
sbit bomb = P1^0;

void delayNms(int N) //@11.0592MHz 延时函数
{
unsigned char i;

while(N){
for(i=1275;i>0;i--);
N--;
}
}
void interruptSetUp(){
IP = 0x04;
EA = 1;
EX0 = 1; // allow external interrupt INT0
EX1 = 1;
IT0 = 1; // set edge triggerin
IT1 = 1;
}

void UartInit() //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //设定定时器1为8位自动重装方式
TL1 = 0xFD; //设定定时初值
TH1 = 0xFD; //设定定时器重装值
TR1 = 1; //启动定时器1
ET1 = 0; //禁止定时器1中断
EA=1; //开放总中断
ES=1; //开放串口中断

}
void Uartsend(unsigned char byte)//发送
{
receivedMessage[r]=byte;//把数据写入发送缓冲区SBUF
r++;
}
void sendSignal(){
char i;
delayNms(300);
for (i=0;i<7;i++)
{
SBUF = Message[i]; //Send one by one each byte to serial
while(TI==0); //Wait for Transmition complition
TI=0; //Clear Transmit Intterupt flag
}

}
void sendReceivedSignal(){
char i;
delayNms(300);
for (i=0;i<r;i++)
{
SBUF = receivedMessage[i]; //Send one by one each byte to serial
while(TI==0); //Wait for Transmition complition
TI=0; //Clear Transmit Intterupt flag
}

}
void UART_ISR() interrupt 4 //串口中断函数
{
if(RI==1)//接收中断
{
Uartsend(SBUF);//把接收的数据发送到计算机
RI=0;//软件清零
}
}
int compareMessage(){
if(receivedMessage[0]=='B'&&receivedMessage[1]=='O'&&receivedMessage[2]=='M'&&receivedMessage[3]=='B')
return 1;
else{
return 0;
}
}
int main()
{
UartInit();
interruptSetUp();

while(1)
{

if(compareMessage()==1){
while(1){

P0=seg[timeS];
delayNms(500);
timeS--;
if(timeS==-1){
sendSignal();
delayNms(10);
bomb=0;
while(1);
}
}
}

}
}

void int0(void) interrupt 0{
while(1){

}
}
void int1(void) interrupt 2{
delayNms(5000);
}#include <REGX52.H>
void UartInit() //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //设定定时器1为8位自动重装方式
TL1 = 0xFD; //设定定时初值
TH1 = 0xFD; //设定定时器重装值
TR1 = 1; //启动定时器1
ET1 = 0; //禁止定时器1中断
EA=1; //开放总中断
ES=1; //开放串口中断
}
void Uartsend(unsigned char byte)//发送
{
SBUF=byte;//把数据写入发送缓冲区SBUF
//数据发送完成的标志是TI=1;所以等待数据传送完
while(TI==0);
TI=0;//软件清零
}
void UART_ISR() interrupt 4//串口中断函数
{
if(RI==1)//接收中断
{
Uartsend(SBUF);//把接收的数据发送到下一个
RI=0;//软件清零
}
}
int main()
{
UartInit();
while(1)
{

}
}

This is the end of our BOMB

Good luck .