UART
原理图
模式 1
配置:
- 1 个起始位, 8 位数据, 1 个停止位;
- 使用定时器 2 作为波特率发生器;
- 允许接收、发送请求中断;
- 将接收到的数据直接发回去,并反转 P1.1 端口的电平。
工程结构:
stc15w204s.h 头文件:
- 声明有关 UART 和定时器 2 的特殊功能寄存器;
- 声明有关 UART 和定时器 2 的特殊功能寄存器的位掩码;
- 以及其他。
#ifndef __STC15W204S_H
#define __STC15W204S_H
//#include<reg51.h>
#define INTERNAL_RC_OSCILLATOR_FREQUENCY_05529600HZ (5529600) /* 5.5296 MHz */
#define INTERNAL_RC_OSCILLATOR_FREQUENCY_06000000HZ (6000000) /* 6.0000 MHz */
#define INTERNAL_RC_OSCILLATOR_FREQUENCY_11059200HZ (11059200) /* 11.0592 MHz */
#define INTERNAL_RC_OSCILLATOR_FREQUENCY_12000000HZ (12000000) /* 12.0000 MHz */
#define INTERNAL_RC_OSCILLATOR_FREQUENCY_18432000HZ (18432000) /* 18.4320 MHz */
#define INTERNAL_RC_OSCILLATOR_FREQUENCY_20000000HZ (20000000) /* 20.0000 MHz */
#define INTERNAL_RC_OSCILLATOR_FREQUENCY_22118400HZ (22118400) /* 22.1184 MHz */
#define INTERNAL_RC_OSCILLATOR_FREQUENCY_24000000HZ (24000000) /* 24.0000 MHz */
#define INTERNAL_RC_OSCILLATOR_FREQUENCY_27000000HZ (27000000) /* 27.0000 MHz */
#define INTERNAL_RC_OSCILLATOR_FREQUENCY_30000000HZ (30000000) /* 30.0000 MHz */
#define INTERNAL_RC_OSCILLATOR_FREQUENCY_33177600HZ (33177600) /* 33.1776 MHz */
#define INTERNAL_RC_OSCILLATOR_FREQUENCY_35000000HZ (35000000) /* 35.0000 MHz */
#define SYSTEM_CLOCK (INTERNAL_RC_OSCILLATOR_FREQUENCY_11059200HZ)
/**
* Interrupt Registers Definition
*/
sfr IE = 0xA8; /* Interrupt Enable Register */
sfr IE2 = 0xAF; /* Interrupt Enable 2 Register */
/**
* Interrupt Registers Bits Definition
*/
/** IE */
#define GLOBAL_IE_EA (0x80)
#define UART_IE_ES (0x10) /* Enable UART interrupt request */
/** IE2 */
#define T2_IE2_ET2 (0x04) /* Timer 2 interrupt enable */
/**
* Power Management Registers Definition
*/
sfr PCON = 0x87; /* Power Control */
/**
* UART Registers Definition
*/
sfr SCON = 0x98; /* Serial Control */
sfr SBUF = 0x99; /* Serial Buffer */
/**
* UART Registers Bits Definition
*/
/** SCON */
#define UART_SCON_SM0 (0x80) /* UART - Serial Mode Selection Bit 0 */
#define UART_SCON_SM1 (0x40) /* UART - Serial Mode Selection Bit 1 */
#define UART_SCON_REN (0x10) /* UART - Receiver Enable */
#define UART_SCON_TI (0x02) /* UART - Transmission Completion Interrupt */
#define UART_SCON_RI (0x01) /* UART - Reception Completion Interrupt */
sbit TI = SCON^1;
sbit RI = SCON^0;
/**
* Timer 2 Registers Definition
*/
sfr T2L = 0xD7; /* Timer 2 Counter Low Register */
sfr T2H = 0xD6; /* Timer 2 Counter High Register */
sfr AUXR = 0x8E; /* Auxiliary Register */
/**
* Timer 2 Registers Bits Definition
*/
/** AUXR */
#define T2_AUXR_T2R (0x10) /* Timer 2 - Run Control */
#define T2_AUXR_T2CT (0x08) /* Timer 2 - Counter or Timer Selection */
#define T2_AUXR_T2x12 (0x04) /* Timer 2 - Speed Control */
#define UART_AUXR_S1ST2 (0x01) /* UART - Serial 1 (UART) Select Timer 2 Acts As Baud Rate Generator */
/**
* Port 1 Registers Definition
*/
sfr P1 = 0x90; /* Port 1 Register */
typedef enum {
FALSE = 0,
TRUE = !FALSE
} boolean;
#define enableInterrupts(enable) if(enable) { \
IE |= GLOBAL_IE_EA; \
} else { \
IE &= ~GLOBAL_IE_EA; \
}
#endif
timer2.h 头文件:
#ifndef __STC15W204S_TIMER_2_H
#define __STC15W204S_TIMER_2_H
#include "stc15w204s.h"
typedef enum {
TIMER2_PRESCALER_DIVIDED_BY_1 = 0,
TIMER2_PRESCALER_DIVIDED_BY_12 = 12
} Timer2Prescaler;
typedef struct {
void (*asTimer)(boolean);
void (*setCounter)(unsigned int);
void (*setTimer)(unsigned int);
unsigned int (*getCounter)();
unsigned int (*getTimer)();
void (*setPrescaler)(Timer2Prescaler);
void (*start)(boolean);
void (*enableInterrupt)(boolean);
} Timer2;
extern Timer2 timer2;
/**
* First call to this function to initialize
* the <code>timer2</code> variable.
*/
void Timer2Constructor();
#endif
timer2.c 文件:
#include "timer2.h"
Timer2 timer2;
/**
* If true, timer 2 acts as timer,
* otherwise it acts as counter.
*/
static void asTimer(boolean isTimer) {
if(isTimer) {
AUXR &= ~T2_AUXR_T2CT;
} else {
AUXR |= T2_AUXR_T2CT;
}
}
/**
* Set the initial value of the counter
* or the timer 2.
*/
static void setCounter(unsigned int counter) {
T2H = (counter) >> 8;
T2L = (counter) & 0xff;
}
/**
* Return the value of the counter
* or the timer 2.
*/
static unsigned int getCounter() {
unsigned int counter;
counter = T2H;
counter = (counter << 8) | T2L;
return counter;
}
/**
* Set the prescaler of the timer 2.
*/
static void setPrescaler(Timer2Prescaler prescaler) {
switch(prescaler) {
case TIMER2_PRESCALER_DIVIDED_BY_1:
AUXR |= T2_AUXR_T2x12;
break;
case TIMER2_PRESCALER_DIVIDED_BY_12:
AUXR &= ~T2_AUXR_T2x12;
break;
}
}
/**
* If true, start the timer 2 to run,
* othewise, stop.
*/
static void start(boolean start) {
if(start) {
AUXR |= T2_AUXR_T2R;
} else {
AUXR &= ~T2_AUXR_T2R;
}
}
/**
* If true, enable timer 2 overflow
* interrupt request, othewise, disable.
*/
static void enableInterrupt(boolean enable) {
if (enable) {
IE2 |= T2_IE2_ET2;
} else {
IE2 &= ~T2_IE2_ET2;
}
}
void Timer2Constructor() {
timer2.asTimer = &asTimer;
timer2.setCounter = &setCounter;
timer2.getCounter = &getCounter;
timer2.setTimer = &setCounter;
timer2.getTimer = &getCounter;
timer2.setPrescaler = &setPrescaler;
timer2.start = &start;
timer2.enableInterrupt = &enableInterrupt;
}
uart.h 头文件:
#ifndef __STC15W204S_UART_H
#define __STC15W204S_UART_H
#include "stc15w204s.h"
typedef enum {
UART_MODE_0 = ((unsigned char)0x00), // NO TEST!
UART_MODE_1 = ((unsigned char)0x40),
UART_MODE_2 = ((unsigned char)0x80), // NO TEST!
UART_MODE_3 = ((unsigned char)0xC0) // NO TEST!
} UartMode;
typedef enum {
// In the STC15W204S SOP16, only Timer 2 is available for UART.
UART_BAUD_RATE_GENERATOR_TIMER_2 = ((unsigned char)0x01)
} UartBaudRateGenerator;
typedef enum {
UART_BAUD_RATE_1200 = (1200),
UART_BAUD_RATE_2400 = (2400),
UART_BAUD_RATE_4800 = (4800),
UART_BAUD_RATE_9600 = (9600),
UART_BAUD_RATE_14400 = (14400),
UART_BAUD_RATE_19200 = (19200),
UART_BAUD_RATE_28800 = (28800)
} UartBaudRate;
typedef enum {
UART_INTERRUPT_FLAG_TX = ((unsigned char)0x02),
UART_INTERRUPT_FLAG_RX = ((unsigned char)0x01)
} UartInterruptFlag;
typedef struct {
void (*setMode)(UartMode);
void (*selectBaudRateGenerator)(UartBaudRateGenerator);
void (*setBaudRate)(UartBaudRate);
void (*enableReceiver)(boolean);
void (*clearInterruptFlag)(UartInterruptFlag);
void (*enableInterrupt)(boolean);
} Uart;
extern Uart uart;
/**
* First call to this function to initialize
* the <code>uart</code> variable.
*/
void UartConstructor();
#endif
uart.c 文件:
#include "uart.h"
Uart uart;
/**
* Set the mode of the UART.
*/
static void setMode(UartMode mode) {
switch(mode) {
case UART_MODE_0:
SCON &= ~(UART_SCON_SM0 | UART_SCON_SM1);
break;
case UART_MODE_1:
SCON &= ~UART_SCON_SM0;
SCON |= UART_SCON_SM1;
break;
case UART_MODE_2:
SCON |= UART_SCON_SM0;
SCON &= ~UART_SCON_SM1;
break;
case UART_MODE_3:
SCON |= (UART_SCON_SM0 | UART_SCON_SM1);
break;
}
}
/**
* Set the baud rate generator for the UART communication.
* Be careful, in the STC15W204S SOP16, Timer 1 is unavailable,
* only the Timer 2 can be use as the UART baud rate generator.
* So you must configure the Timer 2 for the UART.
*/
static void selectBaudRateGenerator(UartBaudRateGenerator baudRateGenerator) {
switch(baudRateGenerator) {
case UART_BAUD_RATE_GENERATOR_TIMER_2:
default:
AUXR |= UART_AUXR_S1ST2; // FORCE USE!
break;
}
}
/**
* Set the baud rate of the UART communication.
* Be careful, in the STC15W204S SOP16, Timer 1 is unavailable,
* only the Timer 2 can be use as the UART baud rate generator.
* So you must configure the Timer 2 for the UART.
*/
static void setBaudRate(UartBaudRate baudRate) {
unsigned int counter;
if((AUXR & T2_AUXR_T2x12) == T2_AUXR_T2x12) {
counter = 65536 - (SYSTEM_CLOCK / baudRate / 4);
} else {
counter = 65536 - (SYSTEM_CLOCK / baudRate / 12 / 4);
}
T2H = (counter) >> 8;
T2L = (counter) & 0xff;
}
/**
* If true, enable the receiver,
* otherwise, disable.
*/
static void enableReceiver(boolean enable) {
if(enable) {
SCON |= UART_SCON_REN;
} else {
SCON &= ~UART_SCON_REN;
}
}
/**
* Clears the UART interrupt request flag.
*/
static void clearInterruptFlag(UartInterruptFlag flag) {
switch(flag) {
case UART_INTERRUPT_FLAG_TX:
SCON &= ~UART_SCON_TI;
break;
case UART_INTERRUPT_FLAG_RX:
SCON &= ~UART_SCON_RI;
break;
}
}
/**
* If true, enable UART interrupt request,
* othewise, disable.
*/
static void enableInterrupt(boolean enable) {
if (enable) {
IE |= UART_IE_ES;
} else {
IE &= ~UART_IE_ES;
}
}
void UartConstructor() {
uart.setMode = &setMode;
uart.selectBaudRateGenerator = &selectBaudRateGenerator;
uart.setBaudRate = &setBaudRate;
uart.enableReceiver = &enableReceiver;
uart.clearInterruptFlag = &clearInterruptFlag;
uart.enableInterrupt = &enableInterrupt;
}
main.c 文件:
/**
* STC15W204S-35I SOP16
* UART - Mode 1: 1 start bit, 8 bit data, 1 stop bit
*/
#include "timer2.h"
#include "uart.h"
sbit LED = P1^1;
void main() {
UartConstructor();
Timer2Constructor();
// Timer 2 use for UART baud rate generator
timer2.asTimer(TRUE);
timer2.setPrescaler(TIMER2_PRESCALER_DIVIDED_BY_1);
timer2.start(TRUE);
uart.setMode(UART_MODE_1);
uart.selectBaudRateGenerator(UART_BAUD_RATE_GENERATOR_TIMER_2);
uart.setBaudRate(UART_BAUD_RATE_28800);
uart.enableReceiver(TRUE);
uart.clearInterruptFlag(UART_INTERRUPT_FLAG_TX);
uart.clearInterruptFlag(UART_INTERRUPT_FLAG_RX);
timer2.enableInterrupt(FALSE);
uart.enableInterrupt(TRUE);
enableInterrupts(TRUE);
while(1) {}
}
void uartInterruptService() interrupt 4 {
unsigned char buffer;
if(RI) {
RI = 0;
buffer = SBUF; // Get
SBUF = buffer; // Set
LED = !LED;
}
if(TI) {
TI = 0;
}
}
下载、测试
呃,9600 的通信速度,数据出现丢失!不过可能和硬件有关,因为我使用了杜邦线,可能是导线过长导致的!