⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 testcom.c

📁 Keil C 51单片机串口通信程序, 通过该程序可以了解和使用单片机串口通信
💻 C
📖 第 1 页 / 共 2 页
字号:
	//         。将奇偶值P代替发送字节的bit7(奇偶位);若为奇校验,则将bit7求反;
	//         。发送该字节;
	//
	//     (1B、7D、0P、2S)1位起始位、7位数据位、0位奇偶位、2位停止位;
	//         。将发送字节的bit7置1(停止位);
	//         。发送该字节;
	//
	//     (1B、8D、1P、1S)1位起始位、8位数据位、1位奇偶位、1位停止位;
	//         。将发送的字节送入A,可以得到奇偶值P;
	//         。将奇偶值P复制到TB8(奇偶位);若为奇校验,则将TB8求反;
	//         。发送该字节;
	//
	//     (1B、8D、0P、2S)1位起始位、8位数据位、0位奇偶位、2位停止位;
	//         。将TB8置1(停止位);
	//         。发送A;
	//
	//   数据接收(接收时可以忽略奇偶校验错误):
	//     (1B、8D、0P、1S)1位起始位、8位数据位、0位奇偶位、1位停止位;
	//         。接收该字节
	//
	//     (1B、7D、1P、1S)1位起始位、7位数据位、1位奇偶位、1位停止位;
	//         。将接收的字节送入A,然后清零A.7,可以得到奇偶值P;
	//         。接收字节的bit7和奇偶值P是否相同;若为奇校验,则将bit7求反;
	//         。若相同,接收该字节;否则,丢弃改字节;
	//
	//     (1B、7D、0P、2S)1位起始位、7位数据位、0位奇偶位、2位停止位;
	//         。将接收字节的bit7清0(停止位);
	//         。保存该字节;
	//
	//     (1B、8D、1P、1S)1位起始位、8位数据位、1位奇偶位、1位停止位;
	//         。将接收的字节送入A,可以得到奇偶值P;
	//         。RB8(奇偶位)和奇偶值P是否相同;若为奇校验,则将RB8求反;
	//         。若相同,接收该字节;否则,丢弃改字节;
	//
	//     (1B、8D、0P、2S)1位起始位、8位数据位、0位奇偶位、2位停止位;
	//         。若RB8(停止位)为1,则停止位收取;
	//         。RB8为1,则接收字符;否则丢弃字符;
	//         。也可以不管以上两个条件,直接接收字符。
	// -----------------------------------------------------------------------------------

	ULNG ulTemp = 0, ulTemp1 = 0;

	EA = 0;  // 禁止中断
	REN = 0; // 停止接收

	// ===============================================
	// TMOD: 定时器工作方式控制寄存器,复位后TMOD = 0x00
	// ===============================================
	//  D7   D6   D5   D4   D3   D2   D1   D0
	// -------------------+---------------------------
	//  GATE C//T M1   M0 | GATE C//T M1   M0
	// -------------------+---------------------------
	// ------ 定时器1 -----+--- 定时器0 ---------------
	// M1、M0:工作方式设置;
	//       00-13位计数器;
	//       01-16位计数器;
	//       10-可自动再装入的8位计数器(从THx中自动装到TLx中);
	//       11-把定时器分为两个8为的计数器或关闭定时器1;
	// C//T:1-计数器功能,0-定时器功能;
	// GATE:选通控制;1-同时/INTx为高电平且TRx为1时选通定时器x;
	//       0-每当TRx为1时就选通定时器x;
	// -----------------------------------------------------
	TMOD = TMOD & 0x0F;
	TMOD = TMOD | 0x20;

	// 计算波特率
    // ----------
	// bTHL = 256 - (SMOD ? 2:1) * fosc / 384 / baudrate;
	// fosc / 384 / baudrate 部分是否为零?
	// 为了说明波特率太高,或者晶振频率太低。
	ulTemp1 = cnFosc / 384;
	ulTemp = ulTemp1 / cnBaudRate;

	if (ulTemp) // 晶振频率够高
	{
		// 波特率不是(2^n);则应定时器初值*2,并倍频;如38400时ulTemp=1.5
		if (cnBaudRate * ulTemp != ulTemp1)
		{
			PCON = PCON | 0x80;
			// ulTemp = cnFosc / 384;
			// ulTemp = 2 * ulTemp / cnBaudRate;
			ulTemp = cnFosc / 192;
			ulTemp = ulTemp / cnBaudRate;
		}
		else
			PCON = PCON & 0x7F;
	}
	else
	{
		// 说明晶振太低,应倍频
		PCON = PCON | 0x80;
		ulTemp = 1;
	}

	// 定时器1计数初值
	TH1 = 256 - ulTemp;
    TL1 = TH1;

	SM0 = 0; SM1 = 1; SM2 = 0; // 异步收发,定时器控制;8位数据的异步工作方式;收到字符RI就置1;

	// ======================================================
	// TCON:定时器/计数器控制寄存器;复位后:TCON = 0x00
	// ======================================================
	//   D7    D6    D5    D4    D3    D2    D1    D0
	// --------------------------------------------------------
	//   TF1   TR1   TF0   TR0   IE1   IT1   IE0   IT0
	// --------------------------------------------------------
	// TF1,TF0:定时器x溢出中断标志,当定时器x溢出时由内部硬件至置位,
	//          当CPU转向中断服务程序时,由内部硬件清除;
	// TR1,TR0:定时器运行控制位,由软件置位、清除来控制定时器开启、关闭;
	// IE1,IE0:外部触发中断请求标志;
	// IT1,IT0:外部中断触发方式,1-下降沿触发;0-低电平触发;
	// --------------------------------------------------------
	TR1 = 1; // 开启定时器1

	EA = 1;  // 开放中断
	REN = 1; // 允许接收
}

// T0中断服务程序: 100us中断一次
void timer0() interrupt 1  /* 1  0x0B Timer 0 */
{
	ucMsCount ++; // 用于1ms计时
	if (ucMsCount >= 10)
	{
		ucMsCount = 0;
		uiMsNow ++; // 当前毫秒数(受GPS脉冲控制)

		if ((uiMsNow % 250) == 0)
			b250MsPassed = 1; // 已经过了250毫秒, LED-RUN

		if (uiMsNow >= 1000)
		{
			uiMsNow = 0;
			bOneSecPassed = 1; // 已经过了1秒

			ucSecCount ++; // 用于1s计时(受GPS脉冲控制)

			if (ucSecCount >= 60)
			{
				ucSecCount = 0; // 用于1s计时(受GPS脉冲控制)

				bOneMinPassed = 1; // 每分钟,重新初始化一次串口,以提高可靠性
			}
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
//  以下为串口访问子程序
// -----------------------------------------------------------------------------
//  设计思想:
//    1、接收和发送均采用中断完成;
//    2、接收中断由RI自动完成;串口每收到完整的1个字节时自动将RI置1;
//    3、发送中断由TI和bComSendBufEmpty配合完成;串口每发送完成1个字节时自动将TI置1;
//       因此,当首次发送时应由程序控制将TI置为1;即,首次使用时因bComSendBufEmpty为0,
//       发送字节时程序将TI置1,强制执行串口中断服务程序,以检查是否需要发送和接收串口
//       信息;
/////////////////////////////////////////////////////////////////////////////////

bit bRecv = 0;
BYTE ucChar;

// 串口中断服务程序
void serial(void) interrupt 4	/* 4  0x23 Serial port */
{
	if (TI) // 发送中断有效,可以发送
	{
		TI = 0; // 复位中断标志

		if (bRecv)
		{
			SBUF = ucChar;
			bRecv = 0;
		}
	}

	if (RI)
	{
		// 接收中断有效,接收数据
		RI = 0; // 复位中断标志
	
		bRecv = 1;
		ucChar = SBUF; // 接收一个字节
		
		TI = 1; // 置位中断标志
	}
}

main()
{
	ucMsCount = 0;     // 用于1ms计时
	uiMsNow = 0;       // 当前毫秒数(受GPS脉冲控制)
	b250MsPassed = 0;  // 已经过了250毫秒, LED-RUN
	bOneSecPassed = 0; // 已经过了1秒
	ucSecCount = 0;    // 用于1s计时(受GPS脉冲控制)
	bOneMinPassed = 0; // 每分钟,重新初始化一次串口,以提高可靠性

	bCSX = 0; // 看门狗清零

	vInterruptInitialize(); // 中断初始化

	vSerialInitialize(); // 串口初始化

	do
	{
		if (b250MsPassed)
		{
			b250MsPassed = 0; // 已经过了250毫秒, LED-RUN
			bCSX  = ~bCSX; // 看门狗清零;
		} // if (b250MsPassed)
	} while(1);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -