//*****************************************************   
//Copyright (c) 2021, 苏州华芯微电子股份有限公司
//All rights reserved                                 
//
//文件名称: HS16F3211-TC0
//摘    要: HS16F3211-TC0功能演示
//  		DemoPortOut/PB0输出488Hz占空比50%的波形-TC0实现
//
//当前版本: 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	CLRWDT()	asm("clrwdt")

#define  IIC_SCL		FPB1
#define  IIC_SDA		FPB0

volatile bit TRISB0              @ ((unsigned)&TRISB*8)+0;

#define SDA_OUT  TRISB0 =0
#define SDA_IN	 TRISB0 =1

unchar IICReadData;
/*-------------------------------------------------
 *  函数名：GPIO_Init
 *	功能：  GPIO设置
 *  输入：  无
 *  输出：  无
 --------------------------------------------------*/	
void GPIO_Init(void) 
{
	OPTION= 0b00000010; //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], 预分频配置 010 '8分频
                        
    PORTA = 0b00000000;	
    IOSTA = 0b00000000;	//PA输入输出 0-输出 1-输入
                        //PA口->全输出
	
    PORTB = 0b00000011;	
    IOSTB = 0b00000000;	//PB输入输出 0-输出 1-输入
                        //PB口->全输出
						
	PHCON = 0b11111110;	//PB0口 内部上拉打开
}


//**************中断处理**********************************
void interrupt ISR(void)			//
{
    //定时器TC0的中断处理**********************
	if(FTC0IF) 
	{
		FTC0IF = 0;
	}
}


/*-------------------------------------------------
 *  函数名称：DelayUs
 *  功能：   短延时函数 --4M-2T--大概快1%左右.
 *  输入参数：Time 延时时间长度 延时时长Time*2 Us
 * 	返回参数：无 
 -------------------------------------------------*/
void Delay2Us(void)
{
	unsigned char a=4;
	while(a--);
}

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

/*-------------------------------------------------
 *  函数名：IIC_Start
 *	功能：  产生IIC起始信号
 *  输入：  无
 *  输出：  无
 --------------------------------------------------*/
void IIC_Start(void)
{
	SDA_OUT;              //SDA线输出
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	Delay2Us();
 	IIC_SDA=0;            //START:when CLK is high,DATA change form high to low 
	Delay2Us();
	IIC_SCL=0;            //钳住I2C总线，准备发送或接收数据 
    Delay2Us();
}	  
/*-------------------------------------------------
 *  函数名：IIC_Stop
 *	功能：  产生IIC停止信号
 *  输入：  无
 *  输出：  无
 --------------------------------------------------*/
 void IIC_Stop(void)
{
	SDA_OUT;              //SDA线输出
	IIC_SCL=0;
	IIC_SDA=0;            //STOP:when CLK is high DATA change form low to high
 	Delay2Us();
	IIC_SCL=1;
    Delay2Us(); 
	IIC_SDA=1;            //发送I2C总线结束信号
	Delay2Us();							   	
}
/*-------------------------------------------------
 *  函数名：IIC_Wait_Ack
 *	功能：  等待应答信号到来
 *  输入：  无
 *  输出：  返回值：1，接收应答失败
 *               0，接收应答成功
 --------------------------------------------------*/
unsigned char IIC_Wait_Ack(void)
{
	unsigned char ucErrTime=0;      
	SDA_IN;               //SDA设置为输入  
	IIC_SDA=1;
	Delay2Us();	   
	IIC_SCL=1;
	Delay2Us();	 
	while(IIC_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250) //等待超时
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL=0;            //时钟输出0 	   
	return 0;  
} 
/*-------------------------------------------------
 *  函数名：IIC_Ack
 *	功能：  产生ACK应答
 *  输入：  无
 *  输出：  无
 --------------------------------------------------*/
void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT;              //SDA线输出
	IIC_SDA=0;
	Delay2Us();	
	IIC_SCL=1;
	Delay2Us();	
	IIC_SCL=0;
}
/*-------------------------------------------------
 *  函数名：IIC_NAck
 *	功能：  不产生ACK应答
 *  输入：  无
 *  输出：  无
 --------------------------------------------------*/	    
void IIC_NAck(void)
{
	IIC_SCL=0;
	SDA_OUT;              //SDA线输出
	IIC_SDA=1;
	Delay2Us();	
	IIC_SCL=1;
	Delay2Us();	
	IIC_SCL=0;
}					 				     
/*-------------------------------------------------
 *  函数名：IIC_Send_Byte
 *	功能：  IIC发送一个字节
 *  输入：  写入要发送的一个人字节数据txd
 *  输出：  无
 --------------------------------------------------*/		  
void IIC_Send_Byte(unsigned char txd)
{                        
    unsigned char t;   
	SDA_OUT;	          //SDA线输出   
    IIC_SCL=0;            //拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
		if((txd&0x80)>>7)
			IIC_SDA=1;
		else
			IIC_SDA=0;
		txd<<=1; 	  
		Delay2Us();				  
		IIC_SCL=1;
		Delay2Us();	
		IIC_SCL=0;	
		Delay2Us();
    }	 
} 	    
/*-------------------------------------------------
 *  函数名：IIC_Read_Byte
 *	功能：  IIC读一个字节
 *  输入：  无
 *  输出：  读出存储器里面的数据并返回receive
 --------------------------------------------------*/
 unsigned char IIC_Read_Byte(void)
{
	unsigned char i,receive=0;
	SDA_IN;               //SDA设置为输入
    for(i=0;i<8;i++ )
	{
        IIC_SCL=0; 
        Delay2Us();	
     	IIC_SCL=1;
        receive<<=1;
        if(IIC_SDA)receive++;   
		Delay2Us();	
    }					 
    IIC_NAck();           //发送nACK
  
    return receive;
}
/*-------------------------------------------------
 *  函数名：IIC_READ
 *	功能：  IIC读出制定位置的数据
 *  输入：  address
 *  输出：  读出address存储器里面的数据iicdata
 --------------------------------------------------*/
unsigned char IIC_READ(unsigned char address)
{
unsigned char iicdata = 0;
IIC_READ_Begin:
	IIC_Start();
	IIC_Send_Byte(0xa0);
	if(IIC_Wait_Ack())goto IIC_READ_Begin;
	IIC_Send_Byte(address);				//填要读的数据地址
	if(IIC_Wait_Ack())goto IIC_READ_Begin; 
	IIC_Start();
	IIC_Send_Byte(0xa1);
	if(IIC_Wait_Ack())goto IIC_READ_Begin;
	iicdata=IIC_Read_Byte();
	IIC_Stop();		
	return iicdata;
}
 /*-------------------------------------------------
 *  函数名：IIC_WRITE
 *	功能：  IIC把数据data写入制定的位置address
 *  输入：  address，data
 *  输出：  无
 --------------------------------------------------*/
void IIC_WRITE(unsigned char address,unsigned char data)
{
IIC_WRITE_Begin:
	IIC_Start();
	IIC_Send_Byte(0xa0);
	if(IIC_Wait_Ack())goto IIC_WRITE_Begin;

	IIC_Send_Byte(address);
	if(IIC_Wait_Ack())goto IIC_WRITE_Begin;

	IIC_Send_Byte(data);
	if(IIC_Wait_Ack())goto IIC_WRITE_Begin;

	IIC_Stop();
	DelayMs(10);
}
//****主函数****//
void main(void) 
{
    GPIO_Init();
	DelayMs(10);
	IICReadData = IIC_READ(0x01); 		//读取AT24C02 0x00地址EEPROM值 
	IIC_WRITE(0x00, ~IICReadData); 		//取反写入地址0x01
    while(1)
    {
      	CLRWDT();
    }
}
