STC15使用PCA0和PCA1做的模拟串口

Posted perseverance52

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STC15使用PCA0和PCA1做的模拟串口相关的知识,希望对你有一定的参考价值。

【STC15】使用PCA0和PCA1做的模拟串口


通过STC官方所给的《STC15系列库函数与例程测试版V2.0》里面的示例,实测,使用STC15W408AS测试,使用内部时钟频率为11.0592MHz时,模拟串口,9600或者19200波特率通讯才正常,22.1184MHz时钟输出波特率设置了几个推荐值值,通讯都是乱码。

  • 采用其他波特率和时钟频率通讯时乱码应该是和位处理时间有关系。
UART3_BitTime	(MAIN_Fosc / UART3_Baudrate)

  • 在串口使用比较紧张的情况下,模拟串口提供了另外一种补充。它利用的是PCA中断,也就是说,不依赖于默认串口(P30、P31)中断。

使用注意事项

  • 模拟串口端口只能是P_RX3: P2^5、和P_TX3:P2^6,对调都不行,否则模拟串口会不间断发送信息,测试了这组PCA_P24_P25_P26_P27更换其中的其他引脚不行。按理来讲应该这组PCA任意2个都应该可以的。
//===================== 模拟串口相关===========================
sbit P_RX3 = P2^5;	//定义模拟串口接收IO
sbit P_TX3 = P2^6;	//定义模拟串口发送IO

程序代码(C语言版)

代码的功能:实现模拟串口将接收到的数据返回发送。

/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-755-82905966 -------------------------------------------*/
/* --- Tel: 86-755-82948412 -------------------------------------------*/
/* --- Web: www.STCMCU.com --------------------------------------------*/
/* 如果要在文章中应用此代码,请在文章中注明使用了宏晶科技的资料及程序   */
/*---------------------------------------------------------------------*/

/*************	功能说明	**************

使用STC15系列的PCA0和PCA1做的模拟串口. PCA0接收(P2.5), PCA1发送(P2.6).

假定测试芯片的工作频率为22118400Hz. 时钟为5.5296MHZ ~ 35MHZ. 

波特率高,则时钟也要选高, 优先使用 22.1184MHZ, 11.0592MHZ.

测试方法: 上位机发送数据,MCU收到数据后原样返回.

串口固定设置: 1位起始位, 8位数据位, 1位停止位,  波特率在 600 ~ 57600 bps.

1200 ~ 57600 bps @ 33.1776MHZ
 600 ~ 57600 bps @ 22.1184MHZ
 600 ~ 38400 bps @ 18.4320MHZ
 300 ~ 28800 bps @ 11.0592MHZ
 150 ~ 14400 bps @  5.5296MHZ

使用STC15W408AS测试,使用内部时钟频率为11.0592MHz时,模拟串口通讯才正常模拟串口通讯才正常(波特率:9600或者19200),22.1184MHz时钟输出乱码
******************************************/

#include	<reg52.h>

#define MAIN_Fosc		11059200UL	//定义主时钟
#define	UART3_Baudrate	9600UL		//定义波特率
#define	RX_Lenth		16			//接收长度

#define	PCA_P12_P11_P10_P37	(0<<4)
#define	PCA_P34_P35_P36_P37	(1<<4)
#define	PCA_P24_P25_P26_P27	(2<<4)
#define	PCA_Mode_Capture	0
#define	PCA_Mode_SoftTimer	0x48
#define	PCA_Clock_1T		(4<<1)
#define	PCA_Clock_2T		(1<<1)
#define	PCA_Clock_4T		(5<<1)
#define	PCA_Clock_6T		(6<<1)
#define	PCA_Clock_8T		(7<<1)
#define	PCA_Clock_12T		(0<<1)
#define	PCA_Clock_ECI		(3<<1)
#define	PCA_Rise_Active		(1<<5)
#define	PCA_Fall_Active		(1<<4)
#define	PCA_PWM_8bit		(0<<6)
#define	PCA_PWM_7bit		(1<<6)
#define	PCA_PWM_6bit		(2<<6)
//位时间处理
#define	UART3_BitTime	(MAIN_Fosc / UART3_Baudrate)

#define		ENABLE		1
#define		DISABLE		0

typedef 	unsigned char	u8;
typedef 	unsigned int	u16;
typedef 	unsigned long	u32;

sfr AUXR1 = 0xA2;
sfr CCON = 0xD8;
sfr CMOD = 0xD9;
sfr CCAPM0 = 0xDA;		//PCA模块0的工作模式寄存器。
sfr CCAPM1 = 0xDB;		//PCA模块1的工作模式寄存器。
sfr CCAPM2 = 0xDC;		//PCA模块2的工作模式寄存器。

sfr CL     = 0xE9;
sfr CCAP0L = 0xEA;		//PCA模块0的捕捉/比较寄存器低8位。
sfr CCAP1L = 0xEB;		//PCA模块1的捕捉/比较寄存器低8位。
sfr CCAP2L = 0xEC;		//PCA模块2的捕捉/比较寄存器低8位。

sfr CH     = 0xF9;
sfr CCAP0H = 0xFA;		//PCA模块0的捕捉/比较寄存器高8位。
sfr CCAP1H = 0xFB;		//PCA模块1的捕捉/比较寄存器高8位。
sfr CCAP2H = 0xFC;		//PCA模块2的捕捉/比较寄存器高8位。

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。
sbit PPCA  = IP^7;		//PCA 中断 优先级设定位

u16		CCAP0_tmp;
u16		CCAP1_tmp;

u8	Tx3_read;			//发送读指针
u8	Rx3_write;			//接收写指针
u8 	idata	buf3[RX_Lenth];	//接收缓冲

//===================== 模拟串口相关===========================
sbit P_RX3 = P2^5;	//定义模拟串口接收IO
sbit P_TX3 = P2^6;	//定义模拟串口发送IO

u8  Tx3_DAT;		// 发送移位变量, 用户不可见
u8  Rx3_DAT;		// 接收移位变量, 用户不可见
u8  Tx3_BitCnt;		// 发送数据的位计数器, 用户不可见
u8  Rx3_BitCnt;		// 接收数据的位计数器, 用户不可见
u8	Rx3_BUF;		// 接收到的字节, 用户读取
u8	Tx3_BUF;		// 要发送的字节, 用户写入
bit	Rx3_Ring;		// 正在接收标志, 低层程序使用, 用户程序不可见
bit	Tx3_Ting;		// 正在发送标志, 用户置1请求发送, 底层发送完成清0
bit	RX3_End;		// 接收到一个字节, 用户查询 并清0
//=============================================================

void	PCA_Init(void);


/******************** 主函数 **************************/
void main(void)

	
	PCA_Init();	//PCA初始化
	EA = 1;
	
	Tx3_read  = 0;
	Rx3_write = 0;
	Tx3_Ting  = 0;
	Rx3_Ring  = 0;
	RX3_End   = 0;
	Tx3_BitCnt = 0;

	
	while (1)		//user's function
	
		if (RX3_End)		// 检测是否收到一个字节
		
			RX3_End = 0;	// 清除标志
			buf3[Rx3_write] = Rx3_BUF;	// 写入缓冲
			if(++Rx3_write >= RX_Lenth)	Rx3_write = 0;	// 指向下一个位置,  溢出检测
		
		if (!Tx3_Ting)		// 检测是否发送空闲
		
			if (Tx3_read != Rx3_write)	// 检测是否收到过字符
			
				Tx3_BUF = buf3[Tx3_read];	// 从缓冲读一个字符发送
				Tx3_Ting = 1;				// 设置发送标志
				if(++Tx3_read >= RX_Lenth)	Tx3_read = 0;	// 指向下一个位置,  溢出检测
			
		
	



//========================================================================
// 函数: void	PCA_Init(void)
// 描述: PCA初始化程序.
// 参数: none
// 返回: none.
// 版本: V1.0, 2013-11-22
//========================================================================
void	PCA_Init(void)

	CR = 0;
	AUXR1 = (AUXR1 & ~(3<<4)) | PCA_P24_P25_P26_P27;	//切换IO口
	CCAPM0 = (PCA_Mode_Capture | PCA_Fall_Active | ENABLE);	//16位下降沿捕捉中断模式

	CCAPM1    = PCA_Mode_SoftTimer | ENABLE;
	CCAP1_tmp = UART3_BitTime;
	CCAP1L    = (u8)CCAP1_tmp;			//将影射寄存器写入捕获寄存器,先写CCAP0L
	CCAP1H    = (u8)(CCAP1_tmp >> 8);	//后写CCAP0H

	CH = 0;
	CL = 0;
	CMOD  = (CMOD  & ~(7<<1)) | PCA_Clock_1T;			//选择时钟源
	PPCA  = 1;	// 高优先级中断
	CR    = 1;	// 运行PCA定时器

//======================================================================

//========================================================================
// 函数: void	PCA_Handler (void) interrupt 7
// 描述: PCA中断处理程序.
// 参数: None
// 返回: none.
// 版本: V1.0, 2012-11-22
//========================================================================
void	PCA_Handler (void) interrupt 7

	if(CCF0)		//PCA模块0中断
	
		CCF0 = 0;			//清PCA模块0中断标志
		if(Rx3_Ring)		//已收到起始位
		
			if (--Rx3_BitCnt == 0)		//接收完一帧数据
			
				Rx3_Ring = 0;			//停止接收
				Rx3_BUF = Rx3_DAT;		//存储数据到缓冲区
				RX3_End = 1;
				CCAPM0 = (PCA_Mode_Capture | PCA_Fall_Active | ENABLE);	//16位下降沿捕捉中断模式
			
			else
			
				Rx3_DAT >>= 1;			  		//把接收的单b数据 暂存到 RxShiftReg(接收缓冲)
				if(P_RX3) Rx3_DAT |= 0x80;  	//shift RX data to RX buffer
				CCAP0_tmp += UART3_BitTime;		//数据位时间
				CCAP0L = (u8)CCAP0_tmp;			//将影射寄存器写入捕获寄存器,先写CCAP0L
				CCAP0H = (u8)(CCAP0_tmp >> 8);	//后写CCAP0H
			
		
		else
		
			CCAP0_tmp = ((u16)CCAP0H << 8) + CCAP0L;	//读捕捉寄存器
			CCAP0_tmp += (UART3_BitTime / 2 + UART3_BitTime);	//起始位 + 半个数据位
			CCAP0L = (u8)CCAP0_tmp;			//将影射寄存器写入捕获寄存器,先写CCAP0L
			CCAP0H = (u8)(CCAP0_tmp >> 8);	//后写CCAP0H
			CCAPM0 = (PCA_Mode_SoftTimer | ENABLE);	//16位软件定时中断模式
			Rx3_Ring = 1;					//标志已收到起始位
			Rx3_BitCnt = 9;					//初始化接收的数据位数(8个数据位+1个停止位)
		
	

	if(CCF1)	//PCA模块1中断, 16位软件定时中断模式
	
		CCF1 = 0;						//清PCA模块1中断标志
		CCAP1_tmp += UART3_BitTime;
		CCAP1L = (u8)CCAP1_tmp;			//将影射寄存器写入捕获寄存器,先写CCAP0L
		CCAP1H = (u8)(CCAP1_tmp >> 8);	//后写CCAP0H

		if(Tx3_Ting)					// 不发送, 退出
		
			if(Tx3_BitCnt == 0)			//发送计数器为0 表明单字节发送还没开始
			
				P_TX3 = 0;				//发送开始位
				Tx3_DAT = Tx3_BUF;		//把缓冲的数据放到发送的buff
				Tx3_BitCnt = 9;			//发送数据位数 (8数据位+1停止位)
			
			else						//发送计数器为非0 正在发送数据
			
				if (--Tx3_BitCnt == 0)	//发送计数器减为0 表明单字节发送结束
				
					P_TX3 = 1;			//送停止位数据
					Tx3_Ting = 0;		//发送停止
				
				else
				
					Tx3_DAT >>= 1;		//把最低位送到 CY(益处标志位)
					P_TX3 = CY;			//发送一个bit数据
				
			
		
	



没有依赖其他头文件就不上源码文件了。

以上是关于STC15使用PCA0和PCA1做的模拟串口的主要内容,如果未能解决你的问题,请参考以下文章

STC15单片机软串口的使用

stc15f104w模拟串口使用

STC15不同配置模式下的串口输出方式总结

STC15不同配置模式下的串口输出方式总结

STC15W408AS单片机简单串口通信示例

7.STC15W408AS单片机串口通信