51单片机之串口通讯

从51串口驱动可认识基本串口的使用,这里遇到的主要问题是使用assert时,assert的实现也使用了4号串口中断,导致报警,因此采用数码管来

调试,通过数码管来打印一些变量等

另外,单片机能使用的全局变量区好小啊,定义的BUFFER超过64字节就很难编译通过了

比较坑的是定时器溢出率计算,书里和DATASHEET举了半天例子,就是不直接给出算法,以下式子中,9600目标波特率,

11002000是系统时钟
//(TH1)N== 256-9600*12*32/11002000

以下代码实现从串口读取一串数据,遇到回车(0X0D,0X0A)返回原数据,如果数据小于29字节,会在尾巴加上 ok后返回原数据

有什么疑问与不对欢迎大家交流


#include <reg52.h>
#include <string.h>
//#include <assert.h>

//(TH1)N== 256-9600*12*32/11002000 =256- 3.3 USE 253(0xfd)
#define UINT16 unsigned int
#define BYTE   unsigned char
#define UART_MAX_SEND_BUFF		32
#define UART_MAX_RECV_BUFF		32
//#define C51_DEBUG

sbit weBit = P1^6;	//数码管使能脚
sbit duBit = P1^7;	//数码管显示位控制脚
	   
BYTE digitArr[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//0-9,A-F
BYTE weMask[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

//BYTE* testbuff[5] = {"read1","read2","","","",""};

typedef struct
{
	BYTE sendbuff[UART_MAX_SEND_BUFF];
	BYTE recvbuff[UART_MAX_RECV_BUFF];
	BYTE  recvok;//收到0X0D,0X0A通知应用处理
	BYTE   isSending;
	UINT16 sendbytes;
	UINT16 sendindex;
	UINT16 recvindex;	
}UART_DEV_T;

UART_DEV_T uart_dev;
//UINT16 g_timer_cnt = 0;

void Delayms(UINT16 time)		//@11.0592MHz
{
	BYTE  i, j;
	UINT16 k;

	for (k=0;k<time;k++)
	{
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
	}
}

void digit_show_hex(UINT16 left,UINT16 right)
{
	UINT16 i=0;
	BYTE   index = 0;

	for (i=0;i<8;i++)
	{
		P0=0;
	    duBit = 0;
		weBit = 1;
		P0 = weMask[i];
		weBit = 0;
		P0=0;
		duBit = 1;
		if (i<4)
		{
			index = (left>>(4*(3-i)))&0xf;
		}
		else
		{
			index = (right>>(4*(7-i)))&0xf;
		}
		P0=digitArr[index];
		Delayms(2);							
	}
}

void uart_clock_init(void)
{
	TH1 = TL1= 0xfd;
    TMOD = 0x20;//自动装载TH1	
	TR1 = 1;//开始计数
}

void uart_init(void)
{
	//SM0 = 0;
	//SM1 = 1;//模式1
	//SM2 = 1;//收到有效停止位才置中断
	//REN = 1;//允许接收
	SCON = 0x70;
	PCON = PCON&0x3f;//SMOD=0,SMOD0=0
	//IPH=IPH|0x10; 52没有该中断优先级寄存器
	PS=1; //中断优先级较高
	EA = 1;
	ES = 1;//打开中断
	uart_clock_init();
}

void uart_int_process(void) interrupt 4
{
	if (1==RI&&0==uart_dev.recvok)
	{//接收
#ifdef C51_DEBUG
        assert(uart_dev.recvindex<UART_MAX_RECV_BUFF);
#endif		
	    uart_dev.recvbuff[uart_dev.recvindex] = SBUF;
        
	    if (0x0a==uart_dev.recvbuff[uart_dev.recvindex]&&uart_dev.recvindex>0&&0x0d==uart_dev.recvbuff[uart_dev.recvindex-1])
	    {
	        uart_dev.recvok = 1;
	    }
	    
	    uart_dev.recvindex++;

	    if (uart_dev.recvindex>=UART_MAX_RECV_BUFF)
	        uart_dev.recvok = 1;

        if (uart_dev.recvok)
            SCON = 0x60;//停止接收,等待接收数据被处理
		RI = 0;
	}

	if (1==TI)
	{//发送
#ifdef C51_DEBUG
        assert(uart_dev.sendbytes>0);
#endif		

       uart_dev.sendbytes--;

	   if (0==uart_dev.sendbytes)
	   {
	       uart_dev.isSending = 0;
	       uart_dev.sendindex = 0;
	   }
	   else
	   {
#ifdef C51_DEBUG
        assert(uart_dev.sendindex<UART_MAX_SEND_BUFF);
#endif		
	       SBUF=uart_dev.sendbuff[uart_dev.sendindex];
	       uart_dev.sendindex++;
	   }
	   TI = 0;
	   //uart_send_byte = 0xaa;
	}
	ES = 1;	
}

void uart_send_buffer(BYTE* buff,UINT16 size)
{
#ifdef C51_DEBUG
    assert(size<UART_MAX_SEND_BUFF&&0==uart_dev.isSending);
#endif

    memcpy(uart_dev.sendbuff,buff,size);
    uart_dev.sendbytes = size;
    uart_dev.sendindex=1;
    SBUF=uart_dev.sendbuff[0];
    
    uart_dev.isSending = 1;
	
	//ES = 0;//关中断,避免BUFFER出错
	

	//ES = 1;//写完BUFFER,打开中断
}

void main(void)
{
    UINT16 recvLen = 0;
    BYTE   recvByte1;
    BYTE   recvByte2;
	uart_init();
    
    if (0==uart_dev.isSending)
    {
        uart_send_buffer("System Ready!\r\n",15);
    }

	while (1)
	{
        if (uart_dev.recvok)
        {
            recvLen = uart_dev.recvindex;
            
            if (0==uart_dev.isSending)
            {	
                if (uart_dev.recvindex>=3)
                {
                    recvByte1 = uart_dev.recvbuff[uart_dev.recvindex-3];
                    recvByte2 = uart_dev.recvbuff[uart_dev.recvindex-2];
                }
                if (uart_dev.recvindex<UART_MAX_RECV_BUFF-3&&uart_dev.recvindex>=2)
                {
                    memcpy(&uart_dev.recvbuff[uart_dev.recvindex-2]," ok\r\n",5);
                    uart_dev.recvindex+=3;
                }
                uart_send_buffer(uart_dev.recvbuff,uart_dev.recvindex);
                uart_dev.recvok = 0;
                
                uart_dev.recvindex = 0;
                SCON = 0x70;//允许接收
            }
        }
	
		digit_show_hex(recvLen,(recvByte1<<8)|recvByte2);
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值