/*********************************************************
*Copyright (C), 2024, Shanghai Eastsoft Microelectronics Co., Ltd
*文件名:  uart_single_line.c
*作  者:  AE Team
*版  本:  v1.0，编译于iDesigner(v4.2.3.197) + 工具链HRCC(v1.2.0.140)
*日  期:  2024/12/31
*描  述:  UART单线分时通信演示
          PA1: TX/RX
          与上位机通信，波特率9600，复位发送一次"www.essemi.com"，然后循环将接收的数据原样返回。
          注意：数据帧尾必须为0x0D、0x0A（勾选上位机的“发送新行”），数据帧长度勿超过64字节。
*备  注:  本软件仅供学习和演示使用，对用户直接引用代码所带来的风险或后果不承担任何法律责任。
**********************************************************/
#include <hic.h>

#define CLRWDT()   {__Asm CWDT;}        //宏定义清狗指令

unsigned char g_rx_buf[64];
unsigned int g_rx_i = 0;
unsigned int cnt;
unsigned char str[] = "www.essemi.com\r\n";

/******************************************************
函数名：void RAMclear(void)
描  述：RAM区数据清零，RAM区地址0x0000~0x03FF
输入值：无
输出值：无
返回值：无
*******************************************************/
void RAMclear(void)
{
    for (IAAH = 0; IAAH <= 0x03; IAAH++)
    {
        for (IAAL = 0; IAAL < 0xFF; IAAL++)
            IAD = 0x00;

        IAD = 0x00;
    }
}

/******************************************************
函数名：void GPIOInit(void)
描  述：首先初始化所有未用到的IO口为输出低电平
输入值：无
输出值：无
返回值：无
*******************************************************/
void GPIOInit(void)
{
    ANSL = 0xFF;        //选择对应端口为数字IO功能
    ANSH = 0xFF;        //选择对应端口为数字IO功能
    PAT = 0x00;         //所有IO设为输出低电平
    PBT = 0x00;
    PCT = 0x00;
    PA = 0x00;
    PB = 0x00;
    PC = 0x00;
}

/**********************************************
函数名：void main(void)
描  述：主函数
输入值：无
输出值：无
返回值：无
**********************************************/
void main(void)
{
    unsigned char *ptr = str;
//    RAMclear();
    GPIOInit();
    RX0LEN = 0;     //8位数据接收格式
    TX0LEN = 0;     //8位数据发送格式
    BRGH0 = 0;      //波特率低速模式：波特率=Fosc/(64*(BRR<7:0>+1))
    BR0R = 0x19;    //波特率=16MHz/(64*(25+1))≈9600bps
	RX0IOS = 1;     //单线分时通信模式
    PAT1 = 0;       //配置为TX

    RX0EN = 0;       //关闭接收
    TX0EN = 1;       //打开发送

    while (*ptr)        //发送："www.essemi.com"
    {
        while (!TRMT0);

        TX0B = *(ptr++);
        CLRWDT();
    }

    while (!TRMT0);

	cnt = 40000U;
	while(--cnt);

	PAT1 = 1;        //配置为RX
    TX0EN = 0;       //关闭发送
    RX0EN = 1;       //打开接收

    RX0IE = 1;       //接收中断
    GIE = 1;         //打开总中断

    while (1)
    {
        CLRWDT();
    }
}

/**********************************************
函数名：void isr(void) interrupt
描  述：中断服务程序
输入值：无
输出值：无
返回值：无
**********************************************/
void isr(void) interrupt
{
	unsigned int tx_i;

    if (RX0IE == 1 && RX0IF == 1)
    {
        g_rx_buf[g_rx_i++] = RX0B;

        if (g_rx_i > 64)
            g_rx_i = 0;

        if(g_rx_i >= 2 && g_rx_buf[g_rx_i - 2] == 0x0D && g_rx_buf[g_rx_i - 1] == 0x0A)
		{
			cnt = 40000U;
			while(--cnt);

			PAT1 = 0;        //配置为TX
			RX0EN = 0;       //关闭接收
			TX0EN = 1;       //打开发送

			for(tx_i = 0; tx_i < g_rx_i; tx_i++)
			{
				while (!TRMT0);
			    TX0B = g_rx_buf[tx_i];
			}

			g_rx_i = 0;

			while (!TRMT0);

			cnt = 40000U;
			while(--cnt);

			PAT1 = 1;        //配置为RX
			TX0EN = 0;       //关闭发送
			RX0EN = 1;       //打开接收
		}
    }
}
