联系我们 - 广告服务 - 联系电话:
您的当前位置: > 综合 > > 正文

STC - STC15官方库函数 串口操作怎么修改?

来源:CSDN 时间:2022-12-12 09:12:25

文章目录


(资料图片仅供参考)

STC - STC15官方库函数 - 串口操作修改概述调试环境修改完的STC库串口操作main.cSTC15Fxxxx.HUSART.hUSART.C总结END

STC - STC15官方库函数 - 串口操作修改

概述

STC15官方库为 STC15-SOFTWARE-LIB-V1.0.rar, 解开后的文件夹为 STC15系列库函数与例程测试版V2.0.

板子做好了, 在用STC官方库函数写一个出厂测试程序. 写好之后, 只要烧录一个出厂测试程序, 就可以通过半自动测试, 很快能知道焊好的板子元件功能是否正常. 如果不正常, 是哪个元件的操作不正常. 这个时间划算.

刚开个头, 第一步是将下位机的信息上报到PC机的串口助手. 但是发现官方库函数的实现有点问题. 将全局buffer sprintf之后, 用串口发送到上位机, 看到的是乱码. 不使用sprintf就正常. 刚开始排查就以为是C51使用sprintf有特殊的地方, 去看前面踩过坑的同学的笔记. 但是我这情况和他们不一样啊. 我sprintf之后的buffer, 丢到watch窗口是正常的. 继续查STC库串口发送的实现, 发现点问题. STC库实现, 弄了一个发送缓冲区, 发送时, 丢到发送缓冲区就不管了. 如果连续发送大段的文本, 超过缓冲区的大小, 就从buffer[0]开始循环堆数据. 这就导致了送到上位机的数据是不对的. 如果覆盖到汉字部分(汉字只剩下半部分), 就有可能出现乱码.

下位机的收发都是有应答的才对, 不可能那么小的缓冲区就随时丢进去, 也不管发送的原始信息是否发送完. 这样不好. 失去了发送的正确性. 改成了发送一个字符完成, 才发送下一个字符. 每次发送的内容, 都是阻塞发送, 发送任务完成后才离开. 接收不用改, 接收是有缓冲区的, 是靠超时来判断是否接收完. 接收内容一般是命令, 比较短. 可以放到缓冲区里面来. 如果接收的内容比较长, e.g. 升级的2进制内容, 那就需要有收发应答, 不能无脑的一直接收或一直发送.

STC官方库是一个测试版, 2015年以后就没有再修改过了. 估计每个公司都有成熟实现, 所以官方也不怎么上心整理库实现. 官方库的整体架子挺好的, 已经将寄存器操作封装的挺好的了. 估计官方也不知道该怎么升级改进这个库了(已经这么优秀了…). 可以拿官方库为蓝本, 将不适合自己的地方或有错误的地方改掉. 工作量不大.

修正完串口实现后, sprintf正常用, 没特别的. 大段, 连续的文本通过串口上传到上位机, 没看到丢失文本或乱码的情况. 改的还行.

前段时间去查资料, github上已经有大神上传了自己的STC15的库, 不止一个大神的库. 但是这个库本身就比较简单(主要是封装寄存器操作的细节, 这个STC官方已经做的很好了, 剩下的都是一些小bug), 用别人的库不如自己修正, 工作量不大, 理解的还深刻(以后有未知MCU, 如果只有datasheet上的寄存器描述, 可以自己尝试也封装一个库实现), 还适合自己用.

调试环境

MDK5(keil C51)

修改完的STC库串口操作

main.c

这里是测试逻辑, 用来上传大段文本到上位机的串口助手 用到了sprintf格式化buffer, 正常用就好, 没遇到坑, 可能还没遇到呢.

// @file main.c// --------------------------------------------------------------------------------// 头文件包含// --------------------------------------------------------------------------------// 不能包含 STC15F2K60S2.h, 即使是指定了一个不存在的 STC15F2K60S2.h// 如果在指定目录下找不到 STC15F2K60S2.h, 也会去MDK5-C51目录下找// 会和config.h中的STC15Fxxxx.H 中的寄存器定义冲突, 导致编译报错.// #include "stc/STC15F2K60S2.h" // 包含工程目录下的.h// 如果使用STC库方式编程, 包含config.h, 不用再包含 STC*.h(e.g. STC15F2K60S2.h)#include "stc/config.h"#include "stc/usart.h"#include "stc/delay.h"#include// for sprintf#include// for memset// 为了防止不调用所有库中的函数引起的编译警告, 只应在左面板的stc节点下包含必须的.c// --------------------------------------------------------------------------------// 宏定义// --------------------------------------------------------------------------------#define TRUE 1#define FALSE 0#define LINE_60 "------------------------------------------------------------"// --------------------------------------------------------------------------------// 全局变量定义// --------------------------------------------------------------------------------// 在这里定义一个128 bytes的buffer, 编译时, keil C51 经常报错, 将变量移动到非main.c中定义, 然后再非main.c的.h中用extern 声明变量.// 好像不是在这定义全局变量的事情, 有时编译报错, 有时单步调试刚进入main时报错, 可能是keilC51本身的问题.// --------------------------------------------------------------------------------// 函数声明// --------------------------------------------------------------------------------void Hardware_init(void);void UART1_init(void);void UART2_init(void);void process_uart_cmd(void);void disp_app_help_on_uart1(void);// --------------------------------------------------------------------------------// 函数实现// --------------------------------------------------------------------------------int main(void){Hardware_init();PrintString1("me - STC15实验箱4 - 硬件出厂测试程序\r\n");disp_app_help_on_uart1();do {// process_uart_cmd(); // 这是阻塞的在等串口命令, 先不调用// testdisp_app_help_on_uart1(); // 不停的串口输出大段的文本, 看看有没有问题// 串口输出没问题, 挺好的} while (1);// return 0;}void disp_app_help_on_uart1(void){memset(&g_tmp_buf[0], 0, sizeof(g_tmp_buf));sprintf(g_tmp_buf, "%s\r\n", LINE_60); // sprintf正常用就好, 挺正常的.PrintString1(g_tmp_buf);PrintString1("串口命令列表\r\n");memset(g_tmp_buf, 0, sizeof(g_tmp_buf));sprintf(g_tmp_buf, "%s\r\n", LINE_60);PrintString1(g_tmp_buf);PrintString1("1. cmd_test_key\r\n");PrintString1("2. cmd_test_Led\r\n");PrintString1("3. cmd_test_xram\r\n");PrintString1("4. cmd_test_e2prom\r\n");PrintString1("5. cmd_test_pm25\r\n");memset(g_tmp_buf, 0, sizeof(g_tmp_buf));sprintf(g_tmp_buf, "%s\r\n", LINE_60);PrintString1(g_tmp_buf);}void process_uart_cmd(void){u8 i = 0;while (1){delay_ms(1);if(COM1.RX_TimeOut > 0)//超时计数{if(--COM1.RX_TimeOut == 0){if(COM1.RX_Cnt > 0){for(i=0; i<COM1.RX_CNT; i++){TX1_write2buff(RX1_Buffer[i]);//收到的数据原样返回}}COM1.RX_Cnt = 0;}}}}void Hardware_init(void){EA = 0; // 总中断 - 关UART1_init();UART2_init();EA = 1; // 总中断 - 开// 在总中断开之后, 才可以操作和中断相关的操作. e.g. 串口打印// 否则需要等进中断才能设置的标志, 就会死等在那里PrintString1("COM1 - 初始化完成(9600/N/8/1)\r\n");PrintString2("COM2 - 初始化完成(115200/N/8/1)\r\n");}void UART1_init(void){COMx_InitDefineCOMx_InitStructure;//结构定义ES = 0; // 串行中断 - 关// COM1 9600/N/8/1COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;//模式,       UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTxCOMx_InitStructure.UART_BRT_Use   = BRT_Timer1;//使用波特率,   BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)COMx_InitStructure.UART_BaudRate  = 9600ul;//波特率, 一般 110 ~ 115200COMx_InitStructure.Morecommunicate = DISABLE; //多机通讯允许, ENABLE,DISABLECOMx_InitStructure.UART_RxEnable  = ENABLE;//接收允许,   ENABLE或DISABLECOMx_InitStructure.BaudRateDouble = DISABLE;//波特率加倍, ENABLE或DISABLECOMx_InitStructure.UART_Interrupt = ENABLE;//中断允许,   ENABLE或DISABLECOMx_InitStructure.UART_Polity    = PolityLow;//中断优先级, PolityLow,PolityHighCOMx_InitStructure.UART_P_SW      = UART1_SW_P16_P17;//切换端口,   UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17(必须使用内部时钟)COMx_InitStructure.UART_RXD_TXD_Short = DISABLE;//内部短路RXD与TXD, 做中继, ENABLE,DISABLEUSART_Configuration(USART1, &COMx_InitStructure);//初始化串口1 USART1,USART2ES = 1; // 串行中断 - 开}void UART2_init(void){COMx_InitDefineCOMx_InitStructure;//结构定义ES = 0; // 串行中断 - 关// COM2 115200/N/8/1COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;//模式,       UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTxCOMx_InitStructure.UART_BRT_Use   = BRT_Timer2;//使用波特率,   BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)COMx_InitStructure.UART_BaudRate  = 115200ul;//波特率,     110 ~ 115200COMx_InitStructure.Morecommunicate = DISABLE; //多机通讯允许, ENABLE,DISABLECOMx_InitStructure.UART_RxEnable  = ENABLE;//接收允许,   ENABLE或DISABLECOMx_InitStructure.BaudRateDouble = DISABLE;//波特率加倍, ENABLE或DISABLECOMx_InitStructure.UART_Interrupt = ENABLE;//中断允许,   ENABLE或DISABLECOMx_InitStructure.UART_Polity    = PolityLow;//中断优先级, PolityLow,PolityHighCOMx_InitStructure.UART_P_SW      = UART2_SW_P46_P47;//切换端口,   UART2_SW_P10_P11,UART2_SW_P46_P47COMx_InitStructure.UART_RXD_TXD_Short = DISABLE;//内部短路RXD与TXD, 做中继, ENABLE,DISABLEUSART_Configuration(USART2, &COMx_InitStructure);//初始化串口2 USART1,USART2ES = 1; // 串行中断 - 开}

STC15Fxxxx.H

官方有2个宏没有括号包围起来, 可能有点问题, 改了一下.

#ifndef_STC15Fxxxx_H#define_STC15Fxxxx_H#include/*  BYTE Registers  */sfr P0   = 0x80;sfr SP   = 0x81;sfr DPL  = 0x82;sfr DPH  = 0x83;sfrS4CON = 0x84;sfrS4BUF = 0x85;sfr PCON = 0x87;sfr TCON = 0x88;sfr TMOD = 0x89;sfr TL0  = 0x8A;sfr TL1  = 0x8B;sfr TH0  = 0x8C;sfr TH1  = 0x8D;sfrAUXR = 0x8E;sfr WAKE_CLKO = 0x8F;sfr INT_CLKO = 0x8F;sfrAUXR2    = 0x8F;sfr RL_TL0  = 0x8A;sfr RL_TL1  = 0x8B;sfr RL_TH0  = 0x8C;sfr RL_TH1  = 0x8D;sfr P1   = 0x90;sfr P1M1 = 0x91;//P1M1.n,P1M0.n =00--->Standard,01--->push-pull实际上1T的都一样sfr P1M0 = 0x92;//=10--->pure input,11--->open drainsfr P0M1 = 0x93;//P0M1.n,P0M0.n =00--->Standard,01--->push-pullsfr P0M0 = 0x94;//=10--->pure input,11--->open drainsfr P2M1 = 0x95;//P2M1.n,P2M0.n =00--->Standard,01--->push-pullsfr P2M0 = 0x96;//=10--->pure input,11--->open drainsfr CLK_DIV = 0x97;sfr PCON2   = 0x97;sfr SCON  = 0x98;sfr SBUF  = 0x99;sfr S2CON = 0x9A;//sfr S2BUF = 0x9B;//sfr P1ASF = 0x9D;//只写,模拟输入(AD或LVD)选择sfr P2    = 0xA0;sfr BUS_SPEED = 0xA1;sfr AUXR1 = 0xA2;sfr P_SW1 = 0xA2;sfr IE    = 0xA8;sfr SADDR = 0xA9;sfr WKTCL = 0xAA;//唤醒定时器低字节sfr WKTCH = 0xAB;//唤醒定时器高字节sfrS3CON = 0xAC;sfr S3BUF = 0xAD;sfr IE2   = 0xAF;//STC12C5A60S2系列sfr P3    = 0xB0;sfr P3M1  = 0xB1;//P3M1.n,P3M0.n =00--->Standard,01--->push-pullsfr P3M0  = 0xB2;//=10--->pure input,11--->open drainsfr P4M1  = 0xB3;//P4M1.n,P4M0.n =00--->Standard,01--->push-pullsfr P4M0  = 0xB4;//=10--->pure input,11--->open drainsfr IP2   = 0xB5;//STC12C5A60S2系列sfr IPH2  = 0xB6;//STC12C5A60S2系列sfr IPH   = 0xB7;sfr IP        = 0xB8;sfr SADEN     = 0xB9;sfrP_SW2     = 0xBA;sfr ADC_CONTR = 0xBC;//带AD系列sfr ADC_RES   = 0xBD;//带AD系列sfr ADC_RESL  = 0xBE;//带AD系列sfr P4        = 0xC0;sfr WDT_CONTR = 0xC1;sfr IAP_DATA  = 0xC2;sfr IAP_ADDRH = 0xC3;sfr IAP_ADDRL = 0xC4;sfr IAP_CMD   = 0xC5;sfr IAP_TRIG  = 0xC6;sfr IAP_CONTR = 0xC7;sfr ISP_DATA  = 0xC2;sfr ISP_ADDRH = 0xC3;sfr ISP_ADDRL = 0xC4;sfr ISP_CMD   = 0xC5;sfr ISP_TRIG  = 0xC6;sfr ISP_CONTR = 0xC7;sfr P5     = 0xC8;//sfr P5M1   = 0xC9;//P5M1.n,P5M0.n =00--->Standard,01--->push-pullsfr P5M0   = 0xCA;//=10--->pure input,11--->open drainsfr P6M1   = 0xCB;//P5M1.n,P5M0.n =00--->Standard,01--->push-pullsfr P6M0   = 0xCC;//=10--->pure input,11--->open drainsfr SPSTAT = 0xCD;//sfr SPCTL  = 0xCE;//sfr SPDAT  = 0xCF;//sfr PSW  = 0xD0;sfrT4T3M = 0xD1;sfrT4H  = 0xD2;sfrT4L  = 0xD3;sfrT3H  = 0xD4;sfrT3L  = 0xD5;sfrT2H  = 0xD6;sfrT2L  = 0xD7;sfrTH4  = 0xD2;sfrTL4  = 0xD3;sfrTH3  = 0xD4;sfrTL3  = 0xD5;sfrTH2  = 0xD6;sfrTL2  = 0xD7;sfrRL_T4H  = 0xD2;sfrRL_T4L  = 0xD3;sfrRL_T3H  = 0xD4;sfrRL_T3L  = 0xD5;sfrRL_T2H  = 0xD6;sfrRL_T2L  = 0xD7;sfr CCON = 0xD8;//sfr CMOD = 0xD9;//sfr CCAPM0 = 0xDA;//PCA模块0的工作模式寄存器。sfr CCAPM1 = 0xDB;//PCA模块1的工作模式寄存器。sfr CCAPM2 = 0xDC;//PCA模块2的工作模式寄存器。sfr ACC    = 0xE0;sfrP7M1   = 0xE1;sfrP7M0   = 0xE2;sfrP6     = 0xE8;sfr CL     = 0xE9;//sfr CCAP0L = 0xEA;//PCA模块0的捕捉/比较寄存器低8位。sfr CCAP1L = 0xEB;//PCA模块1的捕捉/比较寄存器低8位。sfr CCAP2L = 0xEC;//PCA模块2的捕捉/比较寄存器低8位。sfr B      = 0xF0;sfr PCA_PWM0 = 0xF2;//PCA模块0 PWM寄存器。sfr PCA_PWM1 = 0xF3;//PCA模块1 PWM寄存器。sfr PCA_PWM2 = 0xF4;//PCA模块2 PWM寄存器。sfrP7     = 0xF8;sfr CH     = 0xF9;sfr CCAP0H = 0xFA;//PCA模块0的捕捉/比较寄存器高8位。sfr CCAP1H = 0xFB;//PCA模块1的捕捉/比较寄存器高8位。sfr CCAP2H = 0xFC;//PCA模块2的捕捉/比较寄存器高8位。/*  BIT Registers  *//*  PSW   */sbit CY   = PSW^7;sbit AC   = PSW^6;sbit F0   = PSW^5;sbit RS1  = PSW^4;sbit RS0  = PSW^3;sbit OV   = PSW^2;sbit F1   = PSW^1;sbit P    = PSW^0;/*  TCON  */sbit TF1  = TCON^7;//定时器1溢出中断标志位sbit TR1  = TCON^6;//定时器1运行控制位sbit TF0  = TCON^5;//定时器0溢出中断标志位sbit TR0  = TCON^4;//定时器0运行控制位sbit IE1  = TCON^3;//外中断1标志位sbit IT1  = TCON^2;//外中断1信号方式控制位,1:下降沿中断,0:上升下降均中断。sbit IE0  = TCON^1;//外中断0标志位sbit IT0  = TCON^0;//外中断0信号方式控制位,1:下降沿中断,0:上升下降均中断。/*  P0  */sbit  P00 = P0^0;sbit  P01 = P0^1;sbit  P02 = P0^2;sbit  P03 = P0^3;sbit  P04 = P0^4;sbit  P05 = P0^5;sbit  P06 = P0^6;sbit  P07 = P0^7;/*  P1  */sbit  P10 = P1^0;sbit  P11 = P1^1;sbit  P12 = P1^2;sbit  P13 = P1^3;sbit  P14 = P1^4;sbit  P15 = P1^5;sbit  P16 = P1^6;sbit  P17 = P1^7;sbit  RXD2      = P1^0;sbit  TXD2      = P1^1;sbit  CCP1      = P1^0;sbit  CCP0      = P1^1;sbit  SPI_SS    = P1^2;sbit  SPI_MOSI  = P1^3;sbit  SPI_MISO  = P1^4;sbit  SPI_SCLK  = P1^5;sbit  SPI_SS_2    = P2^4;sbit  SPI_MOSI_2  = P2^3;sbit  SPI_MISO_2  = P2^2;sbit  SPI_SCLK_2  = P2^1;sbit  SPI_SS_3    = P5^4;sbit  SPI_MOSI_3  = P4^0;sbit  SPI_MISO_3  = P4^1;sbit  SPI_SCLK_3  = P4^3;/*  P2  */sbit  P20 = P2^0;sbit  P21 = P2^1;sbit  P22 = P2^2;sbit  P23 = P2^3;sbit  P24 = P2^4;sbit  P25 = P2^5;sbit  P26 = P2^6;sbit  P27 = P2^7;/*  P3  */sbit  P30 = P3^0;sbit  P31 = P3^1;sbit  P32 = P3^2;sbit  P33 = P3^3;sbit  P34 = P3^4;sbit  P35 = P3^5;sbit  P36 = P3^6;sbit  P37 = P3^7;sbit RXD  = P3^0;sbit TXD  = P3^1;sbit INT0 = P3^2;sbit INT1 = P3^3;sbit T0   = P3^4;sbit T1   = P3^5;sbit WR   = P3^6;sbit RD   = P3^7;sbit CCP2  = P3^7;sbit CLKOUT0   = P3^5;sbit CLKOUT1   = P3^4;/*  P4  */sbit  P40 = P4^0;sbit  P41 = P4^1;sbit  P42 = P4^2;sbit  P43 = P4^3;sbit  P44 = P4^4;sbit  P45 = P4^5;sbit  P46 = P4^6;sbit  P47 = P4^7;/*  P5  */sbit  P50 = P5^0;sbit  P51 = P5^1;sbit  P52 = P5^2;sbit  P53 = P5^3;sbit  P54 = P5^4;sbit  P55 = P5^5;sbit  P56 = P5^6;sbit  P57 = P5^7;/*  SCON  */sbit SM0  = SCON^7;//SM0/FESM0 SM1 = 00 ~ 11: 方式0~3sbit SM1  = SCON^6;//sbit SM2  = SCON^5;//多机通讯sbit REN  = SCON^4;//接收允许sbit TB8  = SCON^3;//发送数据第8位sbit RB8  = SCON^2;//接收数据第8位sbit TI   = SCON^1;//发送中断标志位sbit RI   = SCON^0;//接收中断标志位/*  IE   */sbit EA   = IE^7;//中断允许总控制位sbit ELVD = IE^6;//低压监测中断允许位sbit EADC = IE^5;//ADC 中断 允许位sbit ES   = IE^4;//串行中断 允许控制位sbit ET1  = IE^3;//定时中断1允许控制位sbit EX1  = IE^2;//外部中断1允许控制位sbit ET0  = IE^1;//定时中断0允许控制位sbit EX0  = IE^0;//外部中断0允许控制位/*  IP   */ /*sbit PPCA = IP^7;//PCA 中断 优先级设定位sbit PLVD = IP^6; //低压中断 优先级设定位sbit PADC = IP^5; //ADC 中断 优先级设定位sbit PS   = IP^4;//串行中断0优先级设定位sbit PT1  = IP^3;//定时中断1优先级设定位sbit PX1  = IP^2;//外部中断1优先级设定位sbit PT0  = IP^1;//定时中断0优先级设定位sbit PX0  = IP^0;//外部中断0优先级设定位*/sbit ACC0 = ACC^0;sbit ACC1 = ACC^1;sbit ACC2 = ACC^2;sbit ACC3 = ACC^3;sbit ACC4 = ACC^4;sbit ACC5 = ACC^5;sbit ACC6 = ACC^6;sbit ACC7 = ACC^7;sbit B0 = B^0;sbit B1 = B^1;sbit B2 = B^2;sbit B3 = B^3;sbit B4 = B^4;sbit B5 = B^5;sbit B6 = B^6;sbit B7 = B^7;//7     6     5    4    3    2    1     0    Reset Value//sfr IE2       = 0xAF;-     -     -    -    -    -   ESPI  ES2   0000,0000B//Auxiliary Interrupt   #defineSPI_INT_ENABLE()IE2 |=  2//允许SPI中断#defineSPI_INT_DISABLE()IE2 &= ~2//允许SPI中断#defineUART2_INT_ENABLE()IE2 |=  1//允许串口2中断#defineUART2_INT_DISABLE()IE2 &= ~1//允许串口2中断//                                          7     6     5    4    3    2    1    0    Reset Value//sfr IP      = 0xB8; //中断优先级低位      PPCA  PLVD  PADC  PS   PT1  PX1  PT0  PX0   0000,0000//--------sbit PPCA= IP^7;//PCA 模块中断优先级sbit PLVD= IP^6;//低压监测中断优先级sbit PADC= IP^5;//ADC 中断优先级sbit PS   = IP^4;//串行中断0优先级设定位sbit PT1= IP^3;//定时中断1优先级设定位sbit PX1= IP^2;//外部中断1优先级设定位sbit PT0= IP^1;//定时中断0优先级设定位sbit PX0= IP^0;//外部中断0优先级设定位//                                           7      6      5     4     3     2    1     0        Reset Value//sfr IPH   = 0xB7; //中断优先级高位       PPCAH  PLVDH  PADCH  PSH  PT1H  PX1H  PT0H  PX0H   0000,0000//sfr IP2   = 0xB5; //                       -      -      -     -     -     -   PSPI   PS2   xxxx,xx00//sfr IPH2  = 0xB6; //                       -      -      -     -     -     -   PSPIH  PS2H  xxxx,xx00#definePPCAH0x80#definePLVDH0x40#definePADCH0x20#definePSH0x10#definePT1H0x08#definePX1H0x04#definePT0H0x02#definePX0H0x01#definePCA_InterruptFirst()PPCA = 1#defineLVD_InterruptFirst()PLVD = 1#defineADC_InterruptFirst()PADC = 1#defineUART1_InterruptFirst()PS   = 1#defineTimer1_InterruptFirst()PT1  = 1#defineINT1_InterruptFirst()PX1  = 1#defineTimer0_InterruptFirst()PT0  = 1#defineINT0_InterruptFirst()PX0  = 1/*************************************************************************************************/#defineS1_DoubleRate()PCON |= 0x80#defineS1_SHIFT()SCON &= 0x3f#defineS1_8bit()SCON |= 0x40#defineS1_9bit()SCON |= 0xc0#defineS1_RX_Enable()SCON |= 0x10#defineS1_USE_P30P31()P_SW1 &=  ~0xc0//UART1 使用P30 P31口默认#defineS1_USE_P36P37()P_SW1 = (P_SW1 & ~0xc0) | 0x40//UART1 使用P36 P37口#defineS1_USE_P16P17()P_SW1 = (P_SW1 & ~0xc0) | 0x80//UART1 使用P16 P17口#defineS1_TXD_RXD_SHORT()PCON2 |= (1<<4)//将TXD与RXD连接中继输出#defineS1_TXD_RXD_OPEN()PCON2 |= (1<<4)//将TXD与RXD连接中继断开默认#define S1_BRT_UseTimer2()AUXR |=  1;#define S1_BRT_UseTimer1()AUXR &= ~1;//  7      6      5      4      3      2     1     0        Reset Value//sfr S2CON = 0x9A;S2SM0    -    S2SM2  S2REN  S2TB8  S2RB8  S2TI  S2RI      00000000B //S2 Control#defineS2_8bit()S2CON &= ~(1<<7)//串口2模式0,8位UART,波特率 = 定时器2的溢出率 / 4#defineS2_9bit()S2CON |=  (1<<7)//串口2模式1,9位UART,波特率 = 定时器2的溢出率 / 4#defineS2_RX_Enable()S2CON |=  (1<<4)//允许串2接收#defineS2_MODE0()S2CON &= ~(1<<7)//串口2模式0,8位UART,波特率 = 定时器2的溢出率 / 4#defineS2_MODE1()S2CON |=  (1<<7)//串口2模式1,9位UART,波特率 = 定时器2的溢出率 / 4#defineS2_RX_EN()S2CON |=  (1<<4)//允许串2接收#defineS2_RX_Disable()S2CON &= ~(1<<4)//禁止串2接收#defineTI2((S2CON & 2) != 0) // 这个宏, 需要用括号包围起来才靠谱#defineRI2((S2CON & 1) != 0) // 这个宏, 需要用括号包围起来才靠谱#defineSET_TI2()S2CON |=  2#defineCLR_TI2()S2CON &= ~2#defineCLR_RI2()S2CON &= ~1#defineS2TB8_SET()S2CON |=  8#defineS2TB8_CLR()S2CON &= ~8#defineS2_Int_en()IE2   |=  1//串口2允许中断#defineS2_USE_P10P11()P_SW2 &= ~1//UART2 使用P1口默认#defineS2_USE_P46P47()P_SW2 |=  1//UART2 使用P4口#defineS3_USE_P00P01()P_SW2 &= ~2//UART3 使用P0口默认#defineS3_USE_P50P51()P_SW2 |=  2//UART3 使用P5口#defineS4_USE_P02P03()P_SW2 &= ~4//UART4 使用P0口默认#defineS4_USE_P52P53()P_SW2 |=  4//UART4 使用P5口/**********************************************************/#defineTimer0_16bitAutoReload()TMOD &= ~0x03//16位自动重装#defineTimer0_16bit()TMOD  = (TMOD & ~0x03) | 0x01//16位#defineTimer0_8bitAutoReload()TMOD  = (TMOD & ~0x03) | 0x02//8位自动重装#defineTimer0_16bitAutoRL_NoMask()TMOD |=  0x03//16位自动重装不可屏蔽中断#defineTimer0_AsCounterP32()TMOD |=  4//时器0用做计数器#defineTimer0_AsTimer()TMOD &= ~4//时器0用做定时器#defineTimer0_ExtControlP34()TMOD |=  4//时器0由外部INT0高电平允许定时计数#define Timer0_Run() TR0 = 1//允许定时器0计数#define Timer0_Stop() TR0 = 0//禁止定时器0计数#define Timer0_InterruptEnable()ET0 = 1//允许Timer1中断.#define Timer0_InterruptDisable()ET0 = 0//禁止Timer1中断.#defineTimer1_16bitAutoReload()TMOD &= ~0x30//16位自动重装#defineTimer1_16bit()TMOD  = (TMOD & ~0x30) | 0x10//16位#defineTimer1_8bitAutoReload()TMOD  = (TMOD & ~0x30) | 0x20//8位自动重装#defineTimer1_16bitAutoRL_NoMask()TMOD |=  0x30//16位自动重装不可屏蔽中断#defineTimer1_AsCounterP33()TMOD |=  (1<<6)//时器1用做计数器#defineTimer1_AsTimer()TMOD &= ~(1<<6)//时器1用做定时器#defineTimer1_ExtControlP35()TMOD |=  (1<<7)//时器1由外部INT1高电平允许定时计数#define Timer1_Run() TR1 = 1//允许定时器1计数#define Timer1_Stop() TR1 = 0//禁止定时器1计数#define Timer1_InterruptEnable()ET1 = 1//允许Timer1中断.#define Timer1_InterruptDisable()ET1 = 0//禁止Timer1中断.//   7     6       5      4     3      2      1      0    Reset Value//sfr AUXR  = 0x8E;T0x12 T1x12 UART_M0x6  BRTR S2SMOD BRTx12 EXTRAM S1BRS  0000,0000//Auxiliary Register #define Timer0_1T()AUXR |=  (1<<7)//Timer0 clodk = fo#define Timer0_12T()AUXR &= ~(1<<7)//Timer0 clodk = fo/1212分频,default#define Timer1_1T()AUXR |=  (1<<6)//Timer1 clodk = fo#define Timer1_12T()AUXR &= ~(1<<6)//Timer1 clodk = fo/1212分频,default#defineS1_M0x6()AUXR |=  (1<<5)//UART Mode0 Speed is 6x Standard#defineS1_M0x1()AUXR &= ~(1<<5)//default,UART Mode0 Speed is Standard#define Timer2_Run() AUXR |=  (1<<4)//允许定时器2计数#define Timer2_Stop() AUXR &= ~(1<<4)//禁止定时器2计数#defineTimer2_AsCounterP31()AUXR |=  (1<<3)//时器2用做计数器#defineTimer2_AsTimer()AUXR &= ~(1<<3)//时器2用做定时器#define Timer2_1T()AUXR |=  (1<<2)//Timer0 clodk = fo#define Timer2_12T()AUXR &= ~(1<<2)//Timer0 clodk = fo/1212分频,default#define Timer2_InterruptEnable()IE2  |=  (1<<2)//允许Timer2中断.#define Timer2_InterruptDisable()IE2  &= ~(1<<2)//禁止Timer2中断.#define ExternalRAM_enable()AUXR |=  2//允许外部XRAM,禁止使用内部1024RAM#define InternalRAM_enable()AUXR &= ~2//禁止外部XRAM,允许使用内部1024RAM#defineT0_pulseP34_enable()AUXR2 |=  1//允许 T0 溢出脉冲在T0(P3.5)脚输出,Fck0 = 1/2 T0 溢出率,T0可以1T或12T。#defineT0_pulseP34_disable()AUXR2 &= ~1#defineT1_pulseP35_enable()AUXR2 |=  2//允许 T1 溢出脉冲在T1(P3.4)脚输出,Fck1 = 1/2 T1 溢出率,T1可以1T或12T。#defineT1_pulseP35_disable()AUXR2 &= ~2#defineT2_pulseP30_enable()AUXR2 |=  4//允许 T2 溢出脉冲在T1(P3.0)脚输出,Fck2 = 1/2 T2 溢出率,T2可以1T或12T。#defineT2_pulseP30_disable()AUXR2 &= ~4#defineT0_pulseP35(n)ET0=0,Timer0_AsTimer(),Timer0_1T(),Timer0_16bitAutoReload(),TH0=(65536-(n/2+MAIN_Fosc/2)/(n))/256,TL0=(65536-(n/2+MAIN_Fosc/2)/(n))%256,AUXR2 |= bit0,TR0=1//fx=fosc/(2*M)/n,  M=1 or M=12#defineT1_pulseP34(n)ET1=0,Timer1_AsTimer(),Timer1_1T(),Timer1_16bitAutoReload(),TH1=(65536-(n/2+MAIN_Fosc/2)/(n))/256,TL1=(65536-(n/2+MAIN_Fosc/2)/(n))%256,AUXR2 |= bit1,TR1=1//fx=fosc/(2*M)/n,  M=1 or M=12#defineT2_pulseP30(n)Timer2_InterruptDisable(),Timer2_AsTimer(),Timer2_1T(),TH2=(65536-(n/2+MAIN_Fosc/2)/(n))/256,TL2=(65536-(n/2+MAIN_Fosc/2)/(n))%256,AUXR2 |= bit2,Timer2_Run()//fx=fosc/(2*M)/n,  M=1 or M=12#defineTimer0_Load(n)TH0 = (n) / 256,TL0 = (n) % 256#defineTimer1_Load(n)TH1 = (n) / 256,TL1 = (n) % 256#defineTimer2_Load(n)TH2 = (n) / 256,TL2 = (n) % 256#defineTimer0_Load_us(n)TH0=(65536-MainFosc_KHZ*(n)/1000)/256,TL0=(65536-MainFosc_KHZ*(n)/1000)%256#defineTimer1_Load_us(n)TH1=(65536-MainFosc_KHZ*(n)/1000)/256,TL1=(65536-MainFosc_KHZ*(n)/1000)%256#defineTimer2_Load_us(n)TH2=(65536-MainFosc_KHZ*(n)/1000)/256,TL2=(65536-MainFosc_KHZ*(n)/1000)%256//sfr WDT_CONTR = 0xC1; //Watch-Dog-Timer Control register//                                      7     6     5      4       3      2   1   0     Reset Value//                                  WDT_FLAG  -  EN_WDT CLR_WDT IDLE_WDT PS2 PS1 PS0    xx00,0000#define D_WDT_FLAG(1<<7)#define D_EN_WDT(1<<5)#define D_CLR_WDT(1<<4)//auto clear#define D_IDLE_WDT(1<<3)//WDT counter when Idle#define D_WDT_SCALE_20#define D_WDT_SCALE_41#define D_WDT_SCALE_82//T=393216*N/fo#define D_WDT_SCALE_163#define D_WDT_SCALE_324#define D_WDT_SCALE_645#define D_WDT_SCALE_1286#define D_WDT_SCALE_2567#defineWDT_reset(n)WDT_CONTR = D_EN_WDT + D_CLR_WDT + D_IDLE_WDT + (n)//初始化WDT,喂狗//  7     6      5    4     3      2    1     0     Reset Value//sfr PCON   = 0x87;SMOD  SMOD0  LVDF  POF   GF1    GF0   PD   IDL    0001,0000 //Power Control //SMOD//串口双倍速//SMOD0#defineLVDF(1<<5)//P4.6低压检测标志//POF//GF1//GF0//#define D_PD2//set 1, power down mode//#define D_IDLE1//set 1, idle mode#defineMCU_IDLE()PCON |= 1//MCU 进入 IDLE 模式#defineMCU_POWER_DOWN()PCON |= 2//MCU 进入 睡眠 模式//sfr ISP_CMD   = 0xC5;#defineISP_STANDBY()ISP_CMD = 0//ISP空闲命令(禁止)#defineISP_READ()ISP_CMD = 1//ISP读出命令#defineISP_WRITE()ISP_CMD = 2//ISP写入命令#defineISP_ERASE()ISP_CMD = 3//ISP擦除命令//sfr ISP_TRIG  = 0xC6;#define ISP_TRIG()ISP_TRIG = 0x5A,ISP_TRIG = 0xA5//ISP触发命令//  7    6    5      4    3    2    1     0    Reset Value//sfr IAP_CONTR = 0xC7;IAPEN SWBS SWRST CFAIL  -   WT2  WT1   WT0   0000,x000//IAP Control Register#define ISP_EN(1<<7)#define ISP_SWBS(1<<6)#define ISP_SWRST(1<<5)#define ISP_CMD_FAIL(1<<4)#define define="" if="" main_fosc="">= 24000000L)#defineISP_WAIT_FREQUENCYISP_WAIT_30MHZ#elif (MAIN_Fosc >= 20000000L)#defineISP_WAIT_FREQUENCYISP_WAIT_24MHZ#elif (MAIN_Fosc >= 12000000L)#defineISP_WAIT_FREQUENCYISP_WAIT_20MHZ#elif (MAIN_Fosc >= 6000000L)#defineISP_WAIT_FREQUENCYISP_WAIT_12MHZ#elif (MAIN_Fosc >= 3000000L)#defineISP_WAIT_FREQUENCYISP_WAIT_6MHZ#elif (MAIN_Fosc >= 2000000L)#defineISP_WAIT_FREQUENCYISP_WAIT_3MHZ#elif (MAIN_Fosc >= 1000000L)#defineISP_WAIT_FREQUENCYISP_WAIT_2MHZ#else#defineISP_WAIT_FREQUENCYISP_WAIT_1MHZ#endif/* ADC Register *///7       6      5       4         3      2    1    0   Reset Value//sfr ADC_CONTR = 0xBC;ADC_POWER SPEED1 SPEED0 ADC_FLAG ADC_START CHS2 CHS1 CHS0 0000,0000//AD 转换控制寄存器 //sfr ADC_RES  = 0xBD;ADCV.9 ADCV.8 ADCV.7 ADCV.6 ADCV.5 ADCV.4 ADCV.3 ADCV.2  0000,0000//A/D 转换结果高8位 //sfr ADC_RESL = 0xBE;  ADCV.1 ADCV.0  0000,0000//A/D 转换结果低2位//sfr ADC_CONTR  = 0xBC;//直接用MOV操作,不要用与或//sfr SPCTL  = 0xCE;SPI控制寄存器//   7       6       5       4       3       2       1       0    Reset Value//SSIGSPENDORDMSTRCPOLCPHASPR1SPR00x00#defineSPI_SSIG_None()SPCTL |=  (1<<7)//1: 忽略SS脚#defineSPI_SSIG_Enable()SPCTL &= ~(1<<7)//0: SS脚用于决定主从机#defineSPI_Enable()SPCTL |=  (1<<6)//1: 允许SPI#defineSPI_Disable()SPCTL &= ~(1<<6)//0: 禁止SPI#defineSPI_LSB_First()SPCTL |=  (1<<5)//1: LSB先发#defineSPI_MSB_First()SPCTL &= ~(1<<5)//0: MSB先发#defineSPI_Master()SPCTL |=  (1<<4)//1: 设为主机#defineSPI_Slave()SPCTL &= ~(1<<4)//0: 设为从机#defineSPI_SCLK_NormalH()SPCTL |=  (1<<3)//1: 空闲时SCLK为高电平#defineSPI_SCLK_NormalL()SPCTL &= ~(1<<3)//0: 空闲时SCLK为低电平#defineSPI_PhaseH()SPCTL |=  (1<<2)//1: #defineSPI_PhaseL()SPCTL &= ~(1<<2)//0: #defineSPI_Speed(n)SPCTL = (SPCTL & ~3) | (n)//设置速度, 0 -- fosc/4, 1 -- fosc/16, 2 -- fosc/64, 3 -- fosc/128//sfr SPDAT  = 0xCF; //SPI Data Register                                                     0000,0000//sfr SPSTAT  = 0xCD;//SPI状态寄存器//   7       6      5   4   3   2   1   0    Reset Value//SPIFWCOL------#defineSPIF0x80//SPI传输完成标志。写入1清0。#defineWCOL0x40//SPI写冲突标志。写入1清0。#defineSPI_USE_P12P13P14P15()AUXR1 &= 0x0c//将SPI切换到P12(SS) P13(MOSI) P14(MISO) P15(SCLK)(上电默认)。#defineSPI_USE_P24P23P22P21()AUXR1 = (AUXR1 & ~0x0c) | 0x04//将SPI切换到P24(SS) P23(MOSI) P22(MISO) P21(SCLK)。#defineSPI_USE_P54P40P41P43()AUXR1 = (AUXR1 & ~0x0c) | 0x08//将SPI切换到P54(SS) P40(MOSI) P41(MISO) P43(SCLK)。/*;PCA_PWMn:    7       6     5   4   3   2     1       0;EBSn_1EBSn_0----EPCnHEPCnL;B5-B2:保留;B1(EPCnH):在PWM模式下,与CCAPnH组成9位数。;B0(EPCnL):在PWM模式下,与CCAPnL组成9位数。*/#definePWM0_NORMAL()PCA_PWM0 &= ~3//PWM0正常输出(默认)#definePWM0_OUT_0()PCA_PWM0 |=  3//PWM0一直输出0#definePWM0_OUT_1()PCA_PWM0 &= ~3, CCAP0H = 0;//PWM0一直输出1#definePWM1_NORMAL()PCA_PWM1 &= ~3//PWM0正常输出(默认)#definePWM1_OUT_0()PCA_PWM1 |=  3//PWM0一直输出0#definePWM1_OUT_1()PCA_PWM1 &= ~3, CCAP1H = 0;//PWM1一直输出1#definePWM2_NORMAL()PCA_PWM2 &= ~3//PWM1正常输出(默认)#definePWM2_OUT_0()PCA_PWM2 |=  3//PWM2一直输出0#definePWM2_OUT_1()PCA_PWM2 &= ~3, CCAP2H = 0;//PWM2一直输出1//7     6     5     4     3     2     1     0     Reset Value//sfr CCON   = 0xD8;CF    CR    -     -     -    CCF2  CCF1  CCF0   00xx,xx00//PCA 控制寄存器。sbit CCF0  = CCON^0;//PCA 模块0中断标志,由硬件置位,必须由软件清0。sbit CCF1  = CCON^1;//PCA 模块1中断标志,由硬件置位,必须由软件清0。sbit CCF2  = CCON^2;//PCA 模块2中断标志,由硬件置位,必须由软件清0。sbit CR    = CCON^6;//1: 允许PCA计数器计数,必须由软件清0。sbit CF    = CCON^7;//PCA计数器溢出(CH,CL由FFFFH变为0000H)标志。PCA计数器溢出后由硬件置位,必须由软件清0。// 7     6     5     4     3     2     1     0    Reset Value//sfr CMOD  = 0xD9;CIDL   -     -     -   CPS2   CPS1  CPS0  ECF   0xxx,0000//PCA 工作模式寄存器。#define PCA_IDLE_OFF()CMOD |=  (1<<7)//IDLE状态PCA停止计数。#define PCA_IDLE_ON()CMOD &= ~(1<<7)//IDLE状态PCA继续计数。#define PCA_CLK_12T()CMOD &= ~0x0E//PCA计数脉冲选择外部晶振/12。fosc/12#define PCA_CLK_2T()CMOD = (CMOD & ~0x0E) + 2//PCA计数脉冲选择外部晶振/2。fosc/2#define PCA_CLK_T0()CMOD = (CMOD & ~0x0E) + 4//PCA计数脉冲选择Timer0中断,Timer0可通过AUXR寄存器设置成工作在12T或1T模式。#define PCA_CLK_ECI()CMOD = (CMOD & ~0x0E) + 6//PCA计数脉冲选择从ECI/P3.4脚输入的外部时钟,最大 fosc/2。#define PCA_CLK_1T()CMOD = (CMOD & ~0x0E) + 8//PCA计数脉冲选择外部晶振。Fosc/1#define PCA_CLK_4T()CMOD = (CMOD & ~0x0E) + 10//PCA计数脉冲选择外部晶振/4。Fosc/4#define PCA_CLK_6T()CMOD = (CMOD & ~0x0E) + 12//PCA计数脉冲选择外部晶振/6。Fosc/6#define PCA_CLK_8T()CMOD = (CMOD & ~0x0E) + 14//PCA计数脉冲选择外部晶振/8。Fosc/8#define PCA_INT_ENABLE()CMOD |=  1//PCA计数器溢出中断允许位,1---允许CF(CCON.7)产生中断。#define PCA_INT_DISABLE()CMOD &= ~1//PCA计数器溢出中断禁止。//    7      6       5        4       3       2       1      0    Reset Value//sfr AUXR1 = 0xA2;  S1_S1  S1_S0  CCP_S1   CCP_S0  SPI_S1   SPI_S0    -     DPS   0100,0000//Auxiliary Register 1#definePCA_USE_P12P11P10P37()AUXR1 &= ~0x30//将PCA/PWM切换到P12(ECI) P11(CCP0) P10(CCP1) P37(CCP2)(上电默认)。#definePCA_USE_P34P35P36P37()AUXR1 = (AUXR1 & ~0x30) | 0x10//将PCA/PWM切换到P34(ECI) P35(CCP0) P36(CCP1) P37(CCP2)。#definePCA_USE_P24P25P26P27()AUXR1 = (AUXR1 & ~0x30) | 0x20//将PCA/PWM切换到P24(ECI) P25(CCP0) P26(CCP1) P27(CCP2)。#defineDPS_SEL1()AUXR1 |=  1//1:选择DPTR1。#defineDPS_SEL0()AUXR1 &= ~1//0:选择DPTR0(上电默认)。/*7     6      5      4     3     2     1     0     Reset Value//sfr CCAPM0 = 0xDA;PWM 寄存器  -   ECOM0  CAPP0  CAPN0  MAT0  TOG0  PWM0  ECCF0   x000,0000//PCA 模块0 //sfr CCAPM1 = 0xDB;PWM 寄存器  -   ECOM1  CAPP1  CAPN1  MAT1  TOG1  PWM1  ECCF1   x000,0000//PCA 模块1//sfr CCAPM2 = 0xDC;PWM 寄存器  -   ECOM2  CAPP2  CAPN2  MAT2  TOG2  PWM2  ECCF2   x000,0000//PCA 模块2;ECOMn = 1:允许比较功能。;CAPPn = 1:允许上升沿触发捕捉功能。;CAPNn = 1:允许下降沿触发捕捉功能。;MATn  = 1:当匹配情况发生时,允许CCON中的CCFn置位。;TOGn  = 1:当匹配情况发生时,CEXn将翻转。(CEX0/PCA0/PWM0/P3.7,CEX1/PCA1/PWM1/P3.5);PWMn  = 1:将CEXn设置为PWM输出。;ECCFn = 1:允许CCON中的CCFn触发中断。;ECOMn CAPPn CAPNn MATn TOGn PWMn ECCFn;  0     0     0    0    0    0     000H未启用任何功能。;  x     1     0    0    0    0     x 20H16位CEXn上升沿触发捕捉功能。;  x     0     1    0    0    0     x 10H16位CEXn下降沿触发捕捉功能。;  x     1     1    0    0    0     x 30H16位CEXn/PCAn边沿(上、下沿)触发捕捉功能。;  1     0     0    1    0    0     x 48H16位软件定时器。;  1     0     0    1    1    0     x 4CH16位高速脉冲输出。;  1     0     0    0    0    1     042H8位PWM。无中断;  1     1     0    0    0    1     163H8位PWM。低变高可产生中断;  1     0     1    0    0    1     153H8位PWM。高变低可产生中断;  1     1     1    0    0    1     173H8位PWM。低变高或高变低均可产生中断;*******************************************************************;*******************************************************************/#definePCA0_none()CCAPM0 = 0#definePCA0_PWM(nbit)CCAPM0 = 0x42,PCA_PWM0 = (PCA_PWM0 & 0x0c) | ((8-nbit)<<6)#definePCA0_PWM_rise_int(nbit) CCAPM0 = 0x63,PCA_PWM0 = (PCA_PWM0 & 0x0c) | ((8-nbit)<<6)#definePCA0_PWM_fall_int(nbit) CCAPM0 = 0x53,PCA_PWM0 = (PCA_PWM0 & 0x0c) | ((8-nbit)<<6)#definePCA0_PWM_edge_int(nbit) CCAPM0 = 0x73,PCA_PWM0 = (PCA_PWM0 & 0x0c) | ((8-nbit)<<6)#definePCA0_capture_rise()CCAPM0 = (0x20 + 1)#definePCA0_capture_fall()CCAPM0 = (0x10 + 1)#definePCA0_capture_edge()CCAPM0 = (0x30 + 1)#definePCA0_16bit_Timer()CCAPM0 = (0x48 + 1)#definePCA0_High_Pulse()CCAPM0 = (0x4C + 1)#definePCA1_none()CCAPM1 = 0#definePCA1_PWM(nbit)CCAPM1 = 0x42,PCA_PWM1 = (PCA_PWM1 & 0x0c) | ((8-nbit)<<6)#definePCA1_PWM_rise_int(nbit) CCAPM1 = 0x63,PCA_PWM1 = (PCA_PWM1 & 0x0c) | ((8-nbit)<<6)#definePCA1_PWM_fall_int(nbit) CCAPM1 = 0x53,PCA_PWM1 = (PCA_PWM1 & 0x0c) | ((8-nbit)<<6)#definePCA1_PWM_edge_int(nbit) CCAPM1 = 0x73,PCA_PWM1 = (PCA_PWM1 & 0x0c) | ((8-nbit)<<6)#definePCA1_capture_rise()CCAPM1 = (0x20 + 1)#definePCA1_capture_fall()CCAPM1 = (0x10 + 1)#definePCA1_capture_edge()CCAPM1 = (0x30 + 1)#definePCA1_16bit_Timer()CCAPM1 = (0x48 + 1)#definePCA1_High_Pulse()CCAPM1 = (0x4C + 1)#definePCA2_none()CCAPM2 = 0#definePCA2_PWM(nbit)CCAPM2 = 0x42,PCA_PWM2 = (PCA_PWM2 & 0x0c) | ((8-nbit)<<6)#definePCA2_PWM_rise_int(nbit) CCAPM2 = 0x63,PCA_PWM2 = (PCA_PWM2 & 0x0c) | ((8-nbit)<<6)#definePCA2_PWM_fall_int(nbit) CCAPM2 = 0x53,PCA_PWM2 = (PCA_PWM2 & 0x0c) | ((8-nbit)<<6)#definePCA2_PWM_edge_int(nbit) CCAPM2 = 0x73,PCA_PWM2 = (PCA_PWM2 & 0x0c) | ((8-nbit)<<6)#definePCA2_capture_rise()CCAPM2 = (0x20 + 1)#definePCA2_capture_fall()CCAPM2 = (0x10 + 1)#definePCA2_capture_edge()CCAPM2 = (0x30 + 1)#definePCA2_16bit_Timer()CCAPM2 = (0x48 + 1)#definePCA2_High_Pulse()CCAPM2 = (0x4C + 1)/* Above is STC additional SFR or change *//**********************************************************/typedef unsigned charu8;typedef unsigned intu16;typedef unsigned longu32;/**********************************************************/#define NOP1()  _nop_()#define NOP2()  NOP1(),NOP1()#define NOP3()  NOP2(),NOP1()#define NOP4()  NOP3(),NOP1()#define NOP5()  NOP4(),NOP1()#define NOP6()  NOP5(),NOP1()#define NOP7()  NOP6(),NOP1()#define NOP8()  NOP7(),NOP1()#define NOP9()  NOP8(),NOP1()#define NOP10() NOP9(),NOP1()#define NOP11() NOP10(),NOP1()#define NOP12() NOP11(),NOP1()#define NOP13() NOP12(),NOP1()#define NOP14() NOP13(),NOP1()#define NOP15() NOP14(),NOP1()#define NOP16() NOP15(),NOP1()#define NOP17() NOP16(),NOP1()#define NOP18() NOP17(),NOP1()#define NOP19() NOP18(),NOP1()#define NOP20() NOP19(),NOP1()#define NOP21() NOP20(),NOP1()#define NOP22() NOP21(),NOP1()#define NOP23() NOP22(),NOP1()#define NOP24() NOP23(),NOP1()#define NOP25() NOP24(),NOP1()#define NOP26() NOP25(),NOP1()#define NOP27() NOP26(),NOP1()#define NOP28() NOP27(),NOP1()#define NOP29() NOP28(),NOP1()#define NOP30() NOP29(),NOP1()#define NOP31() NOP30(),NOP1()#define NOP32() NOP31(),NOP1()#define NOP33() NOP32(),NOP1()#define NOP34() NOP33(),NOP1()#define NOP35() NOP34(),NOP1()#define NOP36() NOP35(),NOP1()#define NOP37() NOP36(),NOP1()#define NOP38() NOP37(),NOP1()#define NOP39() NOP38(),NOP1()#define NOP40() NOP39(),NOP1()#define NOP(N)  NOP##N()/**********************************************//****************************************************************///sfr INT_CLKO = 0x8F;//附加的 SFR WAKE_CLKO (地址:0x8F)/*    7   6    5    4   3     2        1       0         Reset Value    -  EX4  EX3  EX2  -   T2CLKO   T1CLKO  T0CLKO      0000,0000Bb6 -  EX4      : 外中断INT4允许b5 -  EX3      : 外中断INT3允许b4 -  EX2      : 外中断INT2允许b2 - T1CLKO    : 允许 T2 溢出脉冲在P3.0脚输出,Fck1 = 1/2 T1 溢出率b1 - T1CLKO    : 允许 T1 溢出脉冲在P3.4脚输出,Fck1 = 1/2 T1 溢出率b0 - T0CLKO    : 允许 T0 溢出脉冲在P3.5脚输出,Fck0 = 1/2 T0 溢出率*/#defineLVD_InterruptEnable()ELVD = 1#defineLVD_InterruptDisable()ELVD = 0//sfr WKTCL = 0xAA;//STC11F\10和STC15系列 唤醒定时器低字节//sfr WKTCH = 0xAB;//STC11F\10和STC15系列 唤醒定时器高字节//B7B6B5B4B3B2B1B0B7B6B5B4B3B2B1B0//WKTENS11S10S9S8S7S6S5S4S3S2S1S0n * 560us#defineWakeTimerDisable()WKTCH &= 0x7f//WKTEN = 0禁止睡眠唤醒定时器#defineWakeTimerSet(scale)WKTCL = (scale) % 256,WKTCH = (scale) / 256 | 0x80//WKTEN = 1允许睡眠唤醒定时器//sfr CLK_DIV = 0x97; //Clock Divder 系统时钟分频  -     -      -       -     -  CLKS2 CLKS1 CLKS0 xxxx,x000#defineSYSTEM_CLK_1T()CLK_DIV &= ~0x07//default#defineSYSTEM_CLK_2T()CLK_DIV = (CLK_DIV & ~0x07) | 1#defineSYSTEM_CLK_4T()CLK_DIV = (CLK_DIV & ~0x07) | 2#defineSYSTEM_CLK_8T()CLK_DIV = (CLK_DIV & ~0x07) | 3#defineSYSTEM_CLK_16T()CLK_DIV = (CLK_DIV & ~0x07) | 4#defineSYSTEM_CLK_32T()CLK_DIV = (CLK_DIV & ~0x07) | 5#defineSYSTEM_CLK_64T()CLK_DIV = (CLK_DIV & ~0x07) | 6#defineSYSTEM_CLK_128T()CLK_DIV =  CLK_DIV          | 7#defineMCLKO_P54_None()CLK_DIV &= ~0xc0//主时钟不输出#defineMCLKO_P54_DIV1()CLK_DIV  = (CLK_DIV & ~0xc0) | 0x40//主时钟不分频输出#defineMCLKO_P54_DIV2()CLK_DIV  = (CLK_DIV & ~0xc0) | 0x80//主时钟2分频输出#defineMCLKO_P54_DIV4()CLK_DIV  =  CLK_DIV | 0xc0//主时钟4分频输出#defineMCLKO_P34_None()CLK_DIV &= ~0xc0//主时钟不输出#defineMCLKO_P34_DIV1()CLK_DIV  = (CLK_DIV & ~0xc0) | 0x40//主时钟不分频输出#defineMCLKO_P34_DIV2()CLK_DIV  = (CLK_DIV & ~0xc0) | 0x80//主时钟2分频输出#defineMCLKO_P34_DIV4()CLK_DIV  =  CLK_DIV | 0xc0//主时钟4分频输出//sfr BUS_SPEED = 0xA1; //Stretch register      -   -  -  -   -   -  EXRTS1  EXRTSS0 xxxx,xx10#defineBUS_SPEED_1T()BUS_SPEED = 0#defineBUS_SPEED_2T()BUS_SPEED = 1#defineBUS_SPEED_4T()BUS_SPEED = 2#defineBUS_SPEED_8T()BUS_SPEED = 3/*   interrupt vector */#defineINT0_VECTOR0#defineTIMER0_VECTOR1#defineINT1_VECTOR2#defineTIMER1_VECTOR3#defineUART1_VECTOR4#defineADC_VECTOR5#defineLVD_VECTOR6#definePCA_VECTOR7#defineUART2_VECTOR8#defineSPI_VECTOR9#defineINT2_VECTOR10#defineINT3_VECTOR11#defineTIMER2_VECTOR12#defineINT4_VECTOR16#defineUART3_VECTOR17#defineUART4_VECTOR18#defineTIMER3_VECTOR19#defineTIMER4_VECTOR20#defineTRUE1#defineFALSE0//=============================================================//========================================#definePolityLow0//低优先级中断#definePolityHigh1//高优先级中断//========================================#defineMCLKO_None0#defineMCLKO_DIV11#defineMCLKO_DIV22#defineMCLKO_DIV43#defineENABLE1#defineDISABLE0#defineSTC15F_L2K08S28#defineSTC15F_L2K16S216#defineSTC15F_L2K24S224#defineSTC15F_L2K32S232#defineSTC15F_L2K40S240#defineSTC15F_L2K48S248#defineSTC15F_L2K56S256#defineSTC15F_L2K60S260#defineIAP15F_L2K61S261#endif

USART.h

去掉了发送缓冲区, 使用阻塞发送. 注释掉了一些没用的临时代码(STC官方库中确实有一些临时代码没有注释掉) 添加了一个临时全局buffer, 供格式化字符串用.

#ifndef __USART_H#define __USART_H #include"config.h"// #defineCOM_TX1_Lenth128#defineCOM_RX1_Lenth128#defineCOM_TX2_Lenth128#defineCOM_RX2_Lenth128#defineUSART11#defineUSART22#defineUART_ShiftRight0//同步移位输出#defineUART_8bit_BRTx(1<<6)//8位数据,可变波特率#defineUART_9bit(2<<6)//9位数据,固定波特率#defineUART_9bit_BRTx(3<<6)//9位数据,可变波特率#defineUART1_SW_P30_P310#defineUART1_SW_P36_P37(1<<6)#defineUART1_SW_P16_P17(2<<6)//必须使用内部时钟#defineUART2_SW_P10_P110#defineUART2_SW_P46_P471#defineTimeOutSet15#defineTimeOutSet25#defineBRT_Timer11#defineBRT_Timer22typedef struct{u8id;//串口号// u8TX_read;//发送读指针// u8TX_write;//发送写指针// TI/TI2在上电后为0// 发送一个字节后, 不一定会先进中断, 此时TI标志还是0// 所以需要发送时, 置一个忙标志.// 防止发送一个字节后, 没进串口发送中断了, 就发送下一个字节, 导致发送内容丢失// 在初始化时, 置B_TX_busy = 0.// 在发送时, 等待((0 == TI) && (0 == B_TX_busy))才发送// 在发送前, 置B_TX_busy = 1// 发送后, 就可以离开了.// 在中断中, 清 TI = 0, 清 B_TX_busy = 0// 这样, 就可以保证每一个字节都发送成功.u8B_TX_busy;//忙标志u8 RX_Cnt;//接收字节计数u8RX_TimeOut;//接收超时u8B_RX_OK;//接收块完成} COMx_Define; typedef struct{u8UART_Mode;//模式,         UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTxu8UART_BRT_Use;//使用波特率,   BRT_Timer1,BRT_Timer2u32UART_BaudRate;//波特率,       ENABLE,DISABLEu8Morecommunicate;//多机通讯允许, ENABLE,DISABLEu8UART_RxEnable;//允许接收,   ENABLE,DISABLEu8BaudRateDouble;//波特率加倍, ENABLE,DISABLEu8UART_Interrupt;//中断控制,   ENABLE,DISABLEu8UART_Polity;//优先级,     PolityLow,PolityHighu8UART_P_SW;//切换端口,   UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17(必须使用内部时钟)u8UART_RXD_TXD_Short;//内部短路RXD与TXD, 做中继, ENABLE,DISABLE} COMx_InitDefine; externCOMx_DefineCOM1,COM2;externu8 xdata RX1_Buffer[COM_RX1_Lenth];//接收缓冲externu8 xdata RX2_Buffer[COM_RX2_Lenth];//接收缓冲extern u8 xdata g_tmp_buf[128];u8USART_Configuration(u8 UARTx, COMx_InitDefine *COMx);void TX1_write2buff(u8 dat);//写入发送缓冲,指针+1void TX2_write2buff(u8 dat);//写入发送缓冲,指针+1void PrintString1(u8 *puts);void PrintString2(u8 *puts);//void COMx_write2buff(COMx_Define *COMx, u8 dat);//写入发送缓冲,指针+1//void PrintString(COMx_Define *COMx, u8 *puts);#endif

USART.C

主要是改了串口阻塞发送的操作(如何判断串口数据没发送完) 发送一个字符后, 即使是直接发送, 也不能保证再发送下一个字符时, 上一个字符就发送完了. TI标志只能由串口发送中断程序来修改, 不能在串口中断之外修改. 在串口中断之外, 只能读串口发送字符完成的标志做判断.

#include "USART.h"COMx_DefineCOM1,COM2;// 不要发送缓冲, 直接发送完毕才离开u8 xdata RX1_Buffer[COM_RX1_Lenth];//接收缓冲u8 xdata RX2_Buffer[COM_RX2_Lenth];//接收缓冲u8 xdata g_tmp_buf[128];u8 USART_Configuration(u8 UARTx, COMx_InitDefine *COMx){u8i;u32j;if(UARTx == USART1){COM1.id = 1;COM1.B_TX_busy  = 0;COM1.RX_Cnt     = 0;COM1.RX_TimeOut = 0;COM1.B_RX_OK    = 0;for(i=0; iUART_Mode > UART_9bit_BRTx)return 2;//模式错误if(COMx->UART_Polity == PolityHigh)PS = 1;//高优先级中断elsePS = 0;//低优先级中断SCON = (SCON & 0x3f) | COMx->UART_Mode;if((COMx->UART_Mode == UART_9bit_BRTx) ||(COMx->UART_Mode == UART_8bit_BRTx))//可变波特率{j = (MAIN_Fosc / 4) / COMx->UART_BaudRate;//按1T计算if(j >= 65536UL)return 2;//错误j = 65536UL - j;if(COMx->UART_BRT_Use == BRT_Timer1){TR1 = 0;AUXR &= ~0x01;//S1 BRT Use Timer1;TMOD &= ~(1<<6);//Timer1 set As TimerTMOD &= ~0x30;//Timer1_16bitAutoReload;AUXR |=  (1<<6); timer1="" set="" as="" 1t="" modeth1="(u8)(j">>8);TL1 = (u8)j;ET1 = 0;//禁止中断TMOD &= ~0x40;//定时INT_CLKO &= ~0x02;//不输出时钟TR1  = 1;}else if(COMx->UART_BRT_Use == BRT_Timer2){AUXR &= ~(1<<4);//Timer stopAUXR |= 0x01;//S1 BRT Use Timer2;AUXR &= ~(1<<3);//Timer2 set As TimerAUXR |=  (1<<2); timer2="" set="" as="" 1t="" modeth2="(u8)(j">>8);TL2 = (u8)j;IE2  &= ~(1<<2);//禁止中断AUXR &= ~(1<<3);//定时AUXR |=  (1<<4); timer="" run="" else="" return="" comx-="">UART_Mode == UART_ShiftRight){if(COMx->BaudRateDouble == ENABLE)AUXR |=  (1<<5);//固定波特率SysClk/2elseAUXR &= ~(1<<5); else="" comx-="">UART_Mode == UART_9bit)//固定波特率SysClk*2^SMOD/64{if(COMx->BaudRateDouble == ENABLE)PCON |=  (1<<7);//固定波特率SysClk/32elsePCON &= ~(1<<7); comx-="">UART_Interrupt == ENABLE)ES = 1;//允许中断elseES = 0;//禁止中断if(COMx->UART_RxEnable == ENABLE)REN = 1;//允许接收elseREN = 0;//禁止接收P_SW1 = (P_SW1 & 0x3f) | (COMx->UART_P_SW & 0xc0);//切换IOif(COMx->UART_RXD_TXD_Short == ENABLE)PCON2 |=  (1<<4);//内部短路RXD与TXD, 做中继, ENABLE,DISABLEelsePCON2 &= ~(1<<4);return0;}if(uartx com2.id="2;COM2.B_TX_busy" com2.rx_cnt="0;COM2.RX_TimeOut" com2.b_rx_ok="0;for(i=0;" iuart_mode="=" comx-="">UART_Mode == UART_8bit_BRTx))//可变波特率{if(COMx->UART_Polity == PolityHigh)IP2 |=  1;//高优先级中断elseIP2 &= ~1;//低优先级中断if(COMx->UART_Mode == UART_9bit_BRTx)S2CON |=  (1<<7);//9bitelseS2CON &= ~(1<<7); 8bitj="(MAIN_Fosc" comx-="">UART_BaudRate;//按1T计算if(j >= 65536UL)return 2;//错误j = 65536UL - j;AUXR &= ~(1<<4);//Timer stopAUXR &= ~(1<<3);//Timer2 set As TimerAUXR |=  (1<<2); timer2="" set="" as="" 1t="" modeth2="(u8)(j">>8);TL2 = (u8)j;IE2  &= ~(1<<2);//禁止中断AUXR |=  (1<<4); timer="" run="" elsereturn="" comx-="">UART_Interrupt == ENABLE)IE2   |=  1;//允许中断elseIE2   &= ~1;//禁止中断if(COMx->UART_RxEnable == ENABLE)S2CON |=  (1<<4);//允许接收elseS2CON &= ~(1<<4); p_sw2="(P_SW2" comx-="">UART_P_SW & 0x01);//切换IO}return 0;}/*************** 装载串口发送缓冲 *******************************/void TX1_write2buff(u8 dat){COM1.B_TX_busy = 1; // 设置忙标记SBUF = dat; // 立刻发送do {} while ((0 != TI) || (0 != COM1.B_TX_busy)); // 等待发送完成}void TX2_write2buff(u8 dat){COM2.B_TX_busy = 1; // 设置忙标记S2BUF = dat; // 立刻发送do {} while ((0 != TI2) || (0 != COM2.B_TX_busy)); // 等待发送完成}void PrintString1(u8 *puts){for (; *puts != 0;puts++) {TX1_write2buff(*puts); //遇到停止符0结束}}void PrintString2(u8 *puts){for (; *puts != 0;puts++)  TX2_write2buff(*puts); //遇到停止符0结束}/********************* UART1中断函数************************/void UART1_int (void) interrupt UART1_VECTOR{if(RI){RI = 0;if(COM1.B_RX_OK == 0){if(COM1.RX_Cnt >= COM_RX1_Lenth)COM1.RX_Cnt = 0;RX1_Buffer[COM1.RX_Cnt++] = SBUF;COM1.RX_TimeOut = TimeOutSet1;}}if(TI){// 发送标志, 只由串口中断来清除.TI = 0;COM1.B_TX_busy = 0;}}/********************* UART2中断函数************************/void UART2_int (void) interrupt UART2_VECTOR{if(RI2){CLR_RI2();if(COM2.B_RX_OK == 0){if(COM2.RX_Cnt >= COM_RX2_Lenth)COM2.RX_Cnt = 0;RX2_Buffer[COM2.RX_Cnt++] = S2BUF;COM2.RX_TimeOut = TimeOutSet2;}}if(TI2){// 发送标志, 只由串口中断来清除.CLR_TI2();COM2.B_TX_busy = 0;}}

总结

第三方的库, 如果不是很复杂(觉得自己有能力维护, 工作量又不大), 那就自己搞, 对细节的理解更深刻.

END

责任编辑:

标签:

相关推荐:

精彩放送:

新闻聚焦
Top