糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > STC - STC15官方库函数 - 串口操作修改

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

时间:2024-05-17 08:34:03

相关推荐

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

文章目录

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官方库是一个测试版, 以后就没有再修改过了. 估计每个公司都有成熟实现, 所以官方也不怎么上心整理库实现.

官方库的整体架子挺好的, 已经将寄存器操作封装的挺好的了. 估计官方也不知道该怎么升级改进这个库了(已经这么优秀了…).

可以拿官方库为蓝本, 将不适合自己的地方或有错误的地方改掉. 工作量不大.

修正完串口实现后, 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 <stdio.h> // for sprintf#include <string.h> // 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 <intrins.h>/* 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;//765 4 3 2 10 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中断// 765 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优先级设定位// 765432 10 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;// 76543210 Reset Value//sfr S2CON = 0x9A;S2SM0 - S2SM2 S2REN S2TB8 S2RB8 S2TI S2RI00000000B //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中断.// 76 543210 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// 7654 32 1 0Reset 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,喂狗// 765 432 10Reset 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 54 3 2 10 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 ISP_WAIT_1MHZ7#define ISP_WAIT_2MHZ6#define ISP_WAIT_3MHZ5#define ISP_WAIT_6MHZ4#define ISP_WAIT_12MHZ3#define ISP_WAIT_20MHZ2#define ISP_WAIT_24MHZ1#define ISP_WAIT_30MHZ0#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 65 4 32 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 65 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 65 4 3 21 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//76543210Reset 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。// 76543210 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计数器溢出中断禁止。// 76 5 4 3 2 10 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(上电默认)。/*76543210Reset 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; 000 0 0 0000H未启用任何功能。; x10 0 0 0x 20H16位CEXn上升沿触发捕捉功能。; x01 0 0 0x 10H16位CEXn下降沿触发捕捉功能。; x11 0 0 0x 30H16位CEXn/PCAn边沿(上、下沿)触发捕捉功能。; 100 1 0 0x 48H16位软件定时器。; 100 1 1 0x 4CH16位高速脉冲输出。; 100 0 0 1042H8位PWM。无中断; 110 0 0 1163H8位PWM。低变高可产生中断; 101 0 0 1153H8位PWM。高变低可产生中断; 111 0 0 1173H8位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 32 1 0 Reset Value- EX4 EX3 EX2 - T2CLKO T1CLKO T0CLKO0000,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; i<COM_RX1_Lenth; i++)RX1_Buffer[i] = 0;if(COMx->UART_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 enable}else return 2;//错误}else if(COMx->UART_Mode == UART_ShiftRight){if(COMx->BaudRateDouble == ENABLE)AUXR |= (1<<5);//固定波特率SysClk/2elseAUXR &= ~(1<<5);//固定波特率SysClk/12}else if(COMx->UART_Mode == UART_9bit)//固定波特率SysClk*2^SMOD/64{if(COMx->BaudRateDouble == ENABLE)PCON |= (1<<7);//固定波特率SysClk/32elsePCON &= ~(1<<7);//固定波特率SysClk/64}if(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 == USART2){COM2.id = 2;COM2.B_TX_busy = 0;COM2.RX_Cnt= 0;COM2.RX_TimeOut = 0;COM2.B_RX_OK = 0;for(i=0; i<COM_RX2_Lenth; i++)RX2_Buffer[i] = 0;if((COMx->UART_Mode == UART_9bit_BRTx) ||(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 / 4) / 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 enable}elsereturn 2;//模式错误if(COMx->UART_Interrupt == ENABLE)IE2 |= 1;//允许中断elseIE2 &= ~1;//禁止中断if(COMx->UART_RxEnable == ENABLE)S2CON |= (1<<4);//允许接收elseS2CON &= ~(1<<4);//禁止接收P_SW2 = (P_SW2 & ~1) | (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

如果觉得《STC - STC15官方库函数 - 串口操作修改》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。