做mv主題網(wǎng)站媒體發(fā)稿費(fèi)用
本章介紹如何使用stdio.h庫(kù)函數(shù)仿真串口通訊,學(xué)會(huì)使用view下面的“serial window #1”,實(shí)現(xiàn)模擬串口通訊。
Keil C51中有一些關(guān)鍵字,需要牢記:
interrupt0:指定當(dāng)前函數(shù)為外部中斷0;
interrupt1:指定當(dāng)前函數(shù)為定時(shí)器0中斷;
interrupt2:指定當(dāng)前函數(shù)為外部中斷1;
interrupt3:指定當(dāng)前函數(shù)為定時(shí)器1中斷;
interrupt4:指定當(dāng)前函數(shù)為串口中斷;
?using 0表示當(dāng)前函數(shù)使用第0組寄存器;
using 1表示當(dāng)前函數(shù)使用第1組寄存器;
using 2 表示當(dāng)前函數(shù)使用第2組寄存器;
using 3 表示當(dāng)前函數(shù)使用第3組寄存器;
51單片機(jī)內(nèi)有4個(gè)工作組寄存器,每個(gè)工作組的寄存器是R0--R7。
R0-R7在數(shù)據(jù)存儲(chǔ)器里的實(shí)際地址是由特殊功能寄存器PSW里的RS1、RS0位決定的。
using 0表示設(shè)置 RS1=0,RS0 =0,用第0組寄存器,R0--R7的在數(shù)據(jù)存儲(chǔ)區(qū)里的實(shí)際地址是00H-07H。R0(00H)....R7(07H);
using 1表示設(shè)置 RS1=0,RS0 =1,用第1組寄存器,R0--R7的在數(shù)據(jù)存儲(chǔ)區(qū)里的實(shí)際地址是00H-07H。R0(08H)....R7(0FH);
using 2表示設(shè)置 RS1=1,RS0 =0,用第2組寄存器,R0--R7的在數(shù)據(jù)存儲(chǔ)區(qū)里的實(shí)際地址是08H-0FH。R0(10H)....R7(17H);
using 3表示設(shè)置 RS1=1,RS0 =1,用第3組寄存器,R0--R7的在數(shù)據(jù)存儲(chǔ)區(qū)里的實(shí)際地址是00H-07H。R0(18H)....R7(1FH);
#include <REG51.h> ???//包含頭文件REG51.h,使能51內(nèi)部寄存器;
#include <intrins.h> ?//包含頭文件intrins.h,要放在stdio.h的頭文件之前;
//使能函數(shù): _nop_(); ?相當(dāng)于匯編的NOP指令;
//使能函數(shù): bit ?_testbit_( bit bit_value ); 對(duì)bit_value進(jìn)行測(cè)試,若bit_value=1,返回1,否則返回0;
//使能函數(shù): _cror_( unsigned char x, unsigned char n ); 將字節(jié)型變量x的值,向右循環(huán)移動(dòng)n位,然后將其
//值返回;
//使能函數(shù): _iror_( unsigned int x, ?unsigned char n ); 將雙字節(jié)型變量x的值,向右循環(huán)移動(dòng)n位,然后將
//其值返回;
//使能函數(shù): _lror_( unsigned long x, unsigned char n ); 將4字節(jié)型變量x的值,向右循環(huán)移動(dòng)n位,然后將
//其值返回;
//使能函數(shù): _crol_( unsigned char x, unsigned char n ); 將字節(jié)型變量x的值,向左循環(huán)移動(dòng)n位,然后將其
//值返回;
//使能函數(shù): _irol_( unsigned int x, ?unsigned char n ); 將雙字節(jié)型變量x的值,向左循環(huán)移動(dòng)n位,然后將
//其值返回;
//使能函數(shù): _lrol_( unsigned long x, unsigned char n ); 將4字節(jié)型變量x的值,向左循環(huán)移動(dòng)n位,然后將
//其值返回;
//以上的循環(huán)左移和循環(huán)右移,同C語言的左移和右移是不同的,使用時(shí)要小心;
#include <stdio.h> ?//包含頭文件stdio.h
????//_getkey();從串口讀入一個(gè)字符;
???//putchar();向串口發(fā)送一個(gè)字節(jié);
???//printf();向串口發(fā)送一串字節(jié);
#define OSC_FREQ ????11059200L
#define BAUD_Time 1
#if(BAUD_Time==1)
//若波特率加倍,則使用下面參數(shù);
#define BAUD_57600 ??256 - (OSC_FREQ/192L)/57600L ???//255
#define BAUD_28800 ??256 - (OSC_FREQ/192L)/28800L ???//254
#define BAUD_19200 ??256 - (OSC_FREQ/192L)/19200L ???//253
#define BAUD_14400 ??256 - (OSC_FREQ/192L)/14400L ???//252
#define BAUD_9600 ???256 - (OSC_FREQ/192L)/9600L ????//250
#define BAUD_4800 ???256 - (OSC_FREQ/192L)/4800L ?//244
#define BAUD_2400 ???256 - (OSC_FREQ/192L)/2400L ?//232
#define BAUD_1200 ???256 - (OSC_FREQ/192L)/1200L ?//208
#else
//若波特率不加倍,則使用下面參數(shù);
#define BAUD_9600 ???256 - (OSC_FREQ/384L)/9600L
#define BAUD_4800 ???256 - (OSC_FREQ/384L)/4800L
#define BAUD_1200 ???256 - (OSC_FREQ/384L)/1200L
#endif
#define receive_buffer_size ?40
unsigned char receive_buffer[receive_buffer_size];
unsigned char next_in,next_out;
//函數(shù)功能:接收和發(fā)送中斷服務(wù)函數(shù);
void isr_UART(void) interrupt 4 using 1
{ unsigned char temp;
??if(RI)?//處理接收數(shù)據(jù);
????{ temp=_getkey(); //從串口接收一個(gè)字節(jié);?
??receive_buffer[next_in++]=temp;
??????if(next_in==receive_buffer_size) next_in=0;
}
}
//函數(shù)功能:初始化串口,設(shè)置波特率為9600bps@11.0592MHz,使能接收,使用8位UART,開中斷允許;
void Serial_Port_Initialization()
{ PCON = 0x80;
??SCON=0x50; //串行控制寄存器: SM0,SM1,SM2,REN,TB8,RB8,TI,RI
?????????????//SM1:SM0=01,選擇方式1,SM2=0,表示非多機(jī)通訊,8-bit UART;
?????//REN=1,使能接收;
??TMOD&=0x0f;
??TMOD|= 0x20;
//定時(shí)器方式控制寄存器:GATE1,C/T1,M11,M10,GATE0,C/T0,M01,M00
????????//GATE=0,TR置1便可以啟動(dòng)Timer;GATE=1,TR置1,且INT腳輸入高電平,才可以啟動(dòng)Timer;
???//M11:M10=10,選擇方式2,8位自動(dòng)重裝載;
??TH1=BAUD_9600; ?//TH1: ?reload value for 9600 baud @11.0592MHz;
??TL1=TH1;
??TR1=1; ??//啟動(dòng)Timer1;
??//TI=1; ???//發(fā)送UART的第一個(gè)字節(jié),為下次發(fā)送做準(zhǔn)備;
??TI=0; ???//為下次發(fā)送做準(zhǔn)備;
??RI=0;
??next_in=0;
??next_out=0;
??ES=1; //使能串口接收和發(fā)送中斷;
??EA=1; //開總中斷
}
//函數(shù)功能: 將接收到的數(shù)據(jù)返回給PC;
void send_data_to_pc()
{ while(next_out!=next_in) ?//將接收到的數(shù)據(jù)返回給PC;
?????{ TI=1; //為調(diào)用printf()和putchar()內(nèi)部函數(shù)做準(zhǔn)備;
???printf("receive_buffer[%bd]=%c\n",next_out,receive_buffer[next_out]);
???TI=0; //結(jié)束調(diào)用printf()和putchar()內(nèi)部函數(shù)
????next_out++;
?}
}
//函數(shù)功能: Delay 50us
void delay_50us(unsigned char _50us)
{ while(_50us--)
{ _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
??_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
??_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
??_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
??_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
??_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
??_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
??_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
????}
}
void main(void)
{ Serial_Port_Initialization();
??//初始化串口,設(shè)置波特率為9600bps@11.0592MHz,使能接收,使用8位UART,開中斷允許;
??TI=1;?//為調(diào)用printf()和putchar()內(nèi)部函數(shù)做準(zhǔn)備;
??printf("Start:\n");
??TI=0;?//結(jié)束調(diào)用printf()和putchar()內(nèi)部函數(shù)
??for(;;)
????{ _getkey();?//打開view下面的serial window #1,用鍵盤輸入一個(gè)字符;
??send_data_to_pc(); //將接收到的數(shù)據(jù)返回給PC;
??delay_50us(20); ???//延時(shí)1ms;
??TI=0;?//結(jié)束調(diào)用printf()和putchar()內(nèi)部函數(shù)
}
}