//*****************************************************   
//Copyright (c) 2021, 苏州华芯微电子股份有限公司
//All rights reserved                                 
//
//文件名称: HS16F3211-模拟UART发送
//摘    要: HS16F3211-模拟UART_TX功能演示 9600bps
//  		DemoPortOut/PB0 104us翻转一次 
//			UART_TX/FPB1 串口发送脚
//当前版本: 1.0                                      
//作    者: 华芯微MCU组
//完成日期: 2021.08.31
//*****************************************************   

#include 	<hs16f3211.h> 

//***********************宏定义*****************************
#define  unchar     unsigned char 
#define  unint      unsigned int
#define  unlong     unsigned long

#define  DemoPortOut	FPB0

#define		UART_TX		FPB1 //串口发送脚

#define	CLRWDT()	asm("clrwdt")


bit f_uart_tx_busy; 		//串口发送忙标志位
unsigned char uart_bit_cnt; //串口发送总位数
union {
	struct {
		unsigned int start_bit:1;
		unsigned int data1:8;
		unsigned int data:7;
	} uart_t;
	unsigned int uart_2byte;
} uart_dat;

/*-------------------------------------------------
 *  函数名：uart_tx
 *	功能：  GPIO设置
 *  输入：  dat 需要发送的串口数据
 *  输出：  无
 *  注意：  直接调用是阻塞方式发送，轮询非忙标记再发送实现非阻塞
 --------------------------------------------------*/
void uart_tx(unsigned char dat)
{
	while(f_uart_tx_busy);
	
	uart_dat.uart_2byte = dat;
	uart_dat.uart_2byte <<= 1;		//整体数据左移一位 起始位标记为0（通过左移实现）
	uart_dat.uart_2byte |= 0x0200; 	//停止位标记为1 
	
	uart_bit_cnt=10;  	//1bit起始位 + 8位数据位 + 1停止位 共10位
	f_uart_tx_busy=1;   //标记正在发送
}

/*-------------------------------------------------
 *  函数名：GPIO_Init
 *	功能：  GPIO设置
 *  输入：  无
 *  输出：  无
 --------------------------------------------------*/	
void GPIO_Init(void) 
{
	OPTION= 0b00000000; //Bit7 INT1EDG, 外部中断1触发方式 0 INT1引脚下降沿触发
                        //Bit6 INTEDG, 外部中断 触发方式 0 INT引脚下降沿触发
                        //Bit5 T0CS, TMR0时钟源选择位 0 内部指令时钟
                        //Bit4 T0SE, TMR0时钟源边沿选择位 0 T0CKI引脚下降沿触发计数
                        //Bit3 PSA, 预分频分配位 0 预分频器分配给TMR0
                        //Bit2:0 PS[2:0], 预分频配置 000 '2分频
                        
    PORTA = 0b00000000;	
    IOSTA = 0b00000000;	//PA输入输出 0-输出 1-输入
                        //PA口->全输出

    PORTB = 0b00000000;	
    IOSTB = 0b00000000;	//PB输入输出 0-输出 1-输入
                        //PB口->全输出
}


//**************中断处理**********************************
void interrupt ISR(void)			//
{
    //定时器TMR0的中断处理**********************
	if(FT0IF) 
	{
		FT0IF = 0; //清除TMR0中断标记位 104us中断一次
        
        DemoPortOut = ~DemoPortOut; //10us翻转电平
		
		TMR0 = 162; //TMR0 104us中断一次
        
        if(f_uart_tx_busy)
        {
        	if(uart_dat.uart_t.start_bit)UART_TX=1;
        	else UART_TX=0;
        	
        	uart_dat.uart_2byte >>= 1;
        	
        	uart_bit_cnt--;
        	if(uart_bit_cnt==0) f_uart_tx_busy=0;
        }
	}
}

/*-------------------------------------------------
 *  函数名：DelayMs
 *	功能：  软件延时函数
 *  输入：  延时时间 单位 MS 存在一定的误差
 *  输出：  无
 --------------------------------------------------*/	
void DelayMs(unsigned char delayMs)
{
	unsigned char delay_us;
	while(delayMs--)
	{
		delay_us=247;
		while(delay_us--);
        CLRWDT();
	}
}


unsigned char dat=0;
//****主函数****//
void main(void) 
{
    GPIO_Init();
	
	FT0IF = 0;  //清除TMR0中断标记位
	FT0IE = 1;	//开启TMR0中断
	FGIE  = 1;	//开全局中断
	
    while(1)
    {
      	CLRWDT();
      	uart_tx(0xa5);//阻塞方式发送
		uart_tx(dat++);
		uart_tx(~dat);
		DelayMs(254);
    }
}
