国民技术N32G031系列单片机编程

最近使用国民技术N32G031系列单片机的项目较多,项目功能较为简单,写这篇文章主要是为自己的学习做个总结。

最近的一个项目也是电源控制方面的,软件主要功能如下:

1、控制电源8路输出;

2、使用I2C接口作为从机供主机读取各种电源状态及8路输出的通断控制(I2C1接口暂未使用);

3、使用UART/RS485接口供主机读取各种电源及8路输出的通断控制。

好的,其他的不多说,直接上源代码。

1、main.c

/**
 * @file main.c
 * @author Power
 * @version v1.0.1
 *
 * @copyright Copyright (c) 2022, DS.
 */
 /*
	MIPS的全称是Million Instructions Per Second,
	每秒百万指令(西方或者国际上的计量体系中1M(兆)=100万=1000000);Mhz,是指单片机CPU的主频兆赫兹。
	单条指令执行时间:STM32F10X单片机在主频为72MHz下,C语言程序执行一条指令需要的时间可认为10ns~100ns。
	国民技术系列N32G031 MCU,以主频48MHz为例,这里估算的C语言执行一条指令的时间约为20ns-200ns
*/
 
#include "main.h"


//LED to test system clock frequency
#define		LED_ON()			GPIO_ResetBits(GPIOF, GPIO_PIN_7)
#define		LED_OFF()			GPIO_SetBits(GPIOF, GPIO_PIN_7)

//uint16_t 	led_cnt=0;
volatile uint8_t Flag_1ms;		//1 milli-second overflow flag
//volatile uint8_t cDelay_80ms=0;	//80 milli-seconds overflow flag
volatile uint8_t cDelay_10ms=0; //10 milli-seconds overflow flag
uint16_t run_time=0;//to avoid the malfunction when powered-on, we need to delay some time

extern volatile	struct UART_Data_Struct	UART1_STRUCT;//UART interface, defined in the usart.c file
ALARM_STATUS AlarmStatus;
volatile PS_Open EnableOpen;
uint8_t out_err_filter_cnt=0;
uint8_t ocp_filter_cnt=0;
uint8_t adc_filter_cnt=0;
uint8_t off_filter_cnt=0;

/*===================================================================
					
					Hiccup related variables

====================================================================*/
uint8_t cBurpOnDelay1=0;	//ON state duration in a hiccup period
//uint8_t cDelay1On=0;
uint16_t cDelay1Burp=0;		//OFF state duration in a hiccup period
uint8_t cBurpOn1Flag=0;		//OFF time is timeout and switches to ON state
uint8_t cBurpOnDelay2=0;
uint16_t cDelay2Burp=0;
uint8_t cBurpOn2Flag=0;
uint8_t cBurpOnDelay3=0;
uint16_t cDelay3Burp=0;
uint8_t cBurpOn3Flag=0;
uint8_t cBurpOnDelay4=0;
uint16_t cDelay4Burp=0;
uint8_t cBurpOn4Flag=0;
uint8_t cBurpOnDelay5=0;
uint16_t cDelay5Burp=0;
uint8_t cBurpOn5Flag=0;
uint8_t cBurpOnDelay6=0;
uint16_t cDelay6Burp=0;
uint8_t cBurpOn6Flag=0;
uint8_t cBurpOnDelay7=0;
uint16_t cDelay7Burp=0;
uint8_t cBurpOn7Flag=0;
uint8_t cBurpOnDelay8=0;
uint16_t cDelay8Burp=0;
uint8_t cBurpOn8Flag=0;
uint8_t cBurp1_cnt = 0;	//counter, if the burp lasts 3 cycles, we need to set the interval to 10 seconds.
uint8_t cBurp2_cnt = 0;
uint8_t cBurp3_cnt = 0;
uint8_t cBurp4_cnt = 0;
uint8_t cBurp5_cnt = 0;
uint8_t cBurp6_cnt = 0;
uint8_t cBurp7_cnt = 0;
uint8_t cBurp8_cnt = 0;

/*===================================================================
					
			Other variables, including output error, OCP

====================================================================*/
//VDC and OTP check
uint8_t vdc_ovp_off=0,vdc_ovp_recovered=0;
uint8_t vdc_uvp_off=0,vdc_uvp_recovered=0;
uint8_t otp_off=0,otp_recovered=0;

//output error check
uint8_t v1_ok_H=0,v1_ok_L=0;
uint8_t v2_ok_H=0,v2_ok_L=0;
uint8_t v3_ok_H=0,v3_ok_L=0;
uint8_t v4_ok_H=0,v4_ok_L=0;
uint8_t v5_ok_H=0,v5_ok_L=0;
uint8_t v6_ok_H=0,v6_ok_L=0;
uint8_t v7_ok_H=0,v7_ok_L=0;
uint8_t v8_ok_H=0,v8_ok_L=0;

void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);

///**
//*@name: Process_80MS
//*@description: 80 milli-seconds timeout process
//*@params: none
//*@return: none
//*/
//static void Process_80MS(void)
//{	
//	if(cDelay_80ms >= 80)
//	{
//		cDelay_80ms = 0;		
//		//asm("CLRWDT");		
//		//if(cDelay5S != 0)	cDelay5S--;
//		//if(c54v_OVPOCPDelay1S != 0)	c54v_OVPOCPDelay1S--;
//        //if(cBAT_ONDelay1S != 0)	cBAT_ONDelay1S--;			
//		if(UART1_STRUCT.R_DTSime != 0)//delay about ten seconds
//		{
//			if(--UART1_STRUCT.R_DTSime == 0)
//				USART_Configuration();
//		}
//		
//		if(UART1_STRUCT.T_DTSime != 0) //delay about 250 milli-seconds
//		{
//			if(--UART1_STRUCT.T_DTSime == 0)
//			{
//				USART_Configuration();
//			}
//		}
//	}
//}

/**
*@name: OCP_Process1
*@description: the hiccup process of the first channel
*@params: none
*@return: none
*/
static void OCP_Process1(void)
{
	if(OCP1)//check the OCP pin,1: OCP, 0: normal
	{
		if(cBurpOn1Flag >= 3) cBurpOn1Flag = 3;//still OCP, 20-30 milli-seconds filtering
	}
	else
	{
		cBurpOn1Flag = 0;
		cBurp1_cnt = 0;
	}
	
	if(cBurpOn1Flag >= 3)//OCP occurs
	{
		if(AlarmStatus.alarm.SHORT1 == 0) //the first time the OCP occurs
		{
			if(cBurpOnDelay1 == 0)//decreased in the 10 milli-seconds routine, total 50 milli-seconds
			{
				AlarmStatus.alarm.SHORT1 = 1;
				AlarmStatus.alarm.OCP_BURP_1 = 1;
				if(++cBurp1_cnt > 2) cBurp1_cnt = 3;
			}
		}
	}
	
	if(cBurp1_cnt>=3)//10 seconds period
	{
		if(cDelay1Burp>=BURP_LAST_TIME2)
		{
			cDelay1Burp = 0;
			AlarmStatus.alarm.SHORT1 = 0;
			AlarmStatus.alarm.OCP_BURP_1 = 0;
		}
	}
	else
	{
		if(cDelay1Burp>=BURP_LAST_TIME)//5 seconds period
		{
			cDelay1Burp = 0;
			AlarmStatus.alarm.SHORT1 = 0;
			AlarmStatus.alarm.OCP_BURP_1 = 0;
		}
	}
}

/**
*@name: OCP_Process2
*@description: the hiccup process of the second channel			   
*@params: none
*@return: none
*/
static void OCP_Process2(void)
{	
	if(OCP2)//check the OCP pin,1: OCP, 0: normal
	{
		if(cBurpOn2Flag >= 3) cBurpOn2Flag = 3;//still OCP, 20-30 milli-seconds filtering
	}
	else
	{
		cBurpOn2Flag = 0;
		cBurp2_cnt = 0;
	}
	
	if(cBurpOn2Flag >= 3)//OCP occurs
	{
		if(AlarmStatus.alarm.SHORT2 == 0) //the first time the OCP occurs
		{
			if(cBurpOnDelay2 == 0)//decreased in the 10 milli-seconds routine, total 50 milli-seconds
			{
				AlarmStatus.alarm.SHORT2 = 1;
				AlarmStatus.alarm.OCP_BURP_2 = 1;
				if(++cBurp2_cnt > 2) cBurp2_cnt = 3;
			}
		}
	}
	
	if(cBurp2_cnt>=3)//10 seconds period
	{
		if(cDelay2Burp>=BURP_LAST_TIME2)
		{
			cDelay2Burp = 0;
			AlarmStatus.alarm.SHORT2 = 0;
			AlarmStatus.alarm.OCP_BURP_2 = 0;
		}
	}
	else
	{
		if(cDelay2Burp>=BURP_LAST_TIME)//5 seconds period
		{
			cDelay2Burp = 0;
			AlarmStatus.alarm.SHORT2 = 0;
			AlarmStatus.alarm.OCP_BURP_2 = 0;
		}
	}
}

/**
*@name: OCP_Process3
*@description: the hiccup process of the third channel			   
*@params: none
*@return: none
*/
static void OCP_Process3(void)
{	
	if(OCP3)//check the OCP pin,1: OCP, 0: normal
	{
		if(cBurpOn3Flag >= 3) cBurpOn3Flag = 3;//still OCP, 20-30 milli-seconds filtering
	}
	else
	{
		cBurpOn3Flag = 0;
		cBurp3_cnt = 0;
	}
	
	if(cBurpOn3Flag >= 3)//OCP occurs
	{
		if(AlarmStatus.alarm.SHORT3 == 0) //the first time the OCP occurs
		{
			if(cBurpOnDelay3 == 0)//decreased in the 10 milli-seconds routine, total 50 milli-seconds
			{
				AlarmStatus.alarm.SHORT3 = 1;
				AlarmStatus.alarm.OCP_BURP_3 = 1;
				if(++cBurp3_cnt > 2) cBurp3_cnt = 3;
			}
		}
	}
	
	if(cBurp3_cnt>=3)//10 seconds period
	{
		if(cDelay3Burp>=BURP_LAST_TIME2)
		{
			cDelay3Burp = 0;
			AlarmStatus.alarm.SHORT3 = 0;
			AlarmStatus.alarm.OCP_BURP_3 = 0;
		}
	}
	else
	{
		if(cDelay3Burp>=BURP_LAST_TIME)//5 seconds period
		{
			cDelay3Burp = 0;
			AlarmStatus.alarm.SHORT3 = 0;
			AlarmStatus.alarm.OCP_BURP_3 = 0;
		}
	}
}

/**
*@name: OCP_Process4
*@description: the hiccup process of the fourth channel			   
*@params: none
*@return: none
*/
static void OCP_Process4(void)
{	
	if(OCP4)//check the OCP pin,1: OCP, 0: normal
	{
		if(cBurpOn4Flag >= 3) cBurpOn4Flag = 3;//still OCP, 20-30 milli-seconds filtering
	}
	else
	{
		cBurpOn4Flag = 0;
		cBurp4_cnt = 0;
	}
	
	if(cBurpOn4Flag >= 3)//OCP occurs
	{
		if(AlarmStatus.alarm.SHORT4 == 0) //the first time the OCP occurs
		{
			if(cBurpOnDelay4 == 0)//decreased in the 10 milli-seconds routine, total 50 milli-seconds
			{
				AlarmStatus.alarm.SHORT4 = 1;
				AlarmStatus.alarm.OCP_BURP_4 = 1;
				if(++cBurp4_cnt > 2) cBurp4_cnt = 3;
			}
		}
	}
	
	if(cBurp4_cnt>=3)//10 seconds period
	{
		if(cDelay4Burp>=BURP_LAST_TIME2)
		{
			cDelay4Burp = 0;
			AlarmStatus.alarm.SHORT4 = 0;
			AlarmStatus.alarm.OCP_BURP_4 = 0;
		}
	}
	else
	{
		if(cDelay4Burp>=BURP_LAST_TIME)//5 seconds period
		{
			cDelay4Burp = 0;
			AlarmStatus.alarm.SHORT4 = 0;
			AlarmStatus.alarm.OCP_BURP_4 = 0;
		}
	}
}

/**
*@name: OCP_Process5
*@description: the hiccup process of the fifth channel			   
*@params: none
*@return: none
*/
static void OCP_Process5(void)
{
	if(OCP5)//check the OCP pin,1: OCP, 0: normal
	{
		if(cBurpOn5Flag >= 3) cBurpOn5Flag = 3;//still OCP, 20-30 milli-seconds filtering
	}
	else
	{
		cBurpOn5Flag = 0;
		cBurp5_cnt = 0;
	}
	
	if(cBurpOn5Flag >= 3)//OCP occurs
	{
		if(AlarmStatus.alarm.SHORT5 == 0) //the first time the OCP occurs
		{
			if(cBurpOnDelay5 == 0)//decreased in the 10 milli-seconds routine, total 50 milli-seconds
			{
				AlarmStatus.alarm.SHORT5 = 1;
				AlarmStatus.alarm.OCP_BURP_5 = 1;
				if(++cBurp5_cnt > 2) cBurp5_cnt = 3;
			}
		}
	}
	
	if(cBurp5_cnt>=3)//10 seconds period
	{
		if(cDelay5Burp>=BURP_LAST_TIME2)
		{
			cDelay5Burp = 0;
			AlarmStatus.alarm.SHORT5 = 0;
			AlarmStatus.alarm.OCP_BURP_5 = 0;
		}
	}
	else
	{
		if(cDelay5Burp>=BURP_LAST_TIME)//5 seconds period
		{
			cDelay5Burp = 0;
			AlarmStatus.alarm.SHORT5 = 0;
			AlarmStatus.alarm.OCP_BURP_5 = 0;
		}
	}
}

/**
*@name: OCP_Process6
*@description: the hiccup process of the sixth channel			   
*@params: none
*@return: none
*/
static void OCP_Process6(void)
{
	if(OCP6)//check the OCP pin,1: OCP, 0: normal
	{
		if(cBurpOn6Flag >= 3) cBurpOn6Flag = 3;//still OCP, 20-30 milli-seconds filtering
	}
	else
	{
		cBurpOn6Flag = 0;
		cBurp6_cnt = 0;
	}
	
	if(cBurpOn6Flag >= 3)//OCP occurs
	{
		if(AlarmStatus.alarm.SHORT6 == 0) //the first time the OCP occurs
		{
			if(cBurpOnDelay6 == 0)//decreased in the 10 milli-seconds routine, total 50 milli-seconds
			{
				AlarmStatus.alarm.SHORT6 = 1;
				AlarmStatus.alarm.OCP_BURP_6 = 1;
				if(++cBurp6_cnt > 2) cBurp6_cnt = 3;
			}
		}
	}
	
	if(cBurp6_cnt>=3)//10 seconds period
	{
		if(cDelay6Burp>=BURP_LAST_TIME2)
		{
			cDelay6Burp = 0;
			AlarmStatus.alarm.SHORT6 = 0;
			AlarmStatus.alarm.OCP_BURP_6 = 0;
		}
	}
	else
	{
		if(cDelay6Burp>=BURP_LAST_TIME)//5 seconds period
		{
			cDelay6Burp = 0;
			AlarmStatus.alarm.SHORT6 = 0;
			AlarmStatus.alarm.OCP_BURP_6 = 0;
		}
	}
}

/**
*@name: OCP_Process7
*@description: the hiccup process of the seventh channel			   
*@params: none
*@return: none
*/
static void OCP_Process7(void)
{
	if(OCP7)//check the OCP pin,1: OCP, 0: normal
	{
		if(cBurpOn7Flag >= 3) cBurpOn7Flag = 3;//still OCP, 20-30 milli-seconds filtering
	}
	else
	{
		cBurpOn7Flag = 0;
		cBurp7_cnt = 0;
	}
	
	if(cBurpOn7Flag >= 3)//OCP occurs
	{
		if(AlarmStatus.alarm.SHORT7 == 0) //the first time the OCP occurs
		{
			if(cBurpOnDelay7 == 0)//decreased in the 10 milli-seconds routine, total 50 milli-seconds
			{
				AlarmStatus.alarm.SHORT7 = 1;
				AlarmStatus.alarm.OCP_BURP_7 = 1;
				if(++cBurp7_cnt > 2) cBurp7_cnt = 3;
			}
		}
	}
	
	if(cBurp7_cnt>=3)//10 seconds period
	{
		if(cDelay7Burp>=BURP_LAST_TIME2)
		{
			cDelay7Burp = 0;
			AlarmStatus.alarm.SHORT7 = 0;
			AlarmStatus.alarm.OCP_BURP_7 = 0;
		}
	}
	else
	{
		if(cDelay7Burp>=BURP_LAST_TIME)//5 seconds period
		{
			cDelay7Burp = 0;
			AlarmStatus.alarm.SHORT7 = 0;
			AlarmStatus.alarm.OCP_BURP_7 = 0;
		}
	}
}

/**
*@name: OCP_Process8
*@description: the hiccup process of the eighth channel			   
*@params: none
*@return: none
*/
static void OCP_Process8(void)
{
	if(OCP8)//check the OCP pin,1: OCP, 0: normal
	{
		if(cBurpOn8Flag >= 3) cBurpOn8Flag = 3;//still OCP, 20-30 milli-seconds filtering
	}
	else
	{
		cBurpOn8Flag = 0;
		cBurp8_cnt = 0;
	}
	
	if(cBurpOn8Flag >= 3)//OCP occurs
	{
		if(AlarmStatus.alarm.SHORT8 == 0) //the first time the OCP occurs
		{
			if(cBurpOnDelay8 == 0)//decreased in the 10 milli-seconds routine, total 50 milli-seconds
			{
				AlarmStatus.alarm.SHORT8 = 1;
				AlarmStatus.alarm.OCP_BURP_8 = 1;
				if(++cBurp8_cnt > 2) cBurp8_cnt = 3;
			}
		}
	}
	
	if(cBurp8_cnt>=3)//10 seconds period
	{
		if(cDelay8Burp>=BURP_LAST_TIME2)
		{
			cDelay8Burp = 0;
			AlarmStatus.alarm.SHORT8 = 0;
			AlarmStatus.alarm.OCP_BURP_8 = 0;
		}
	}
	else
	{
		if(cDelay8Burp>=BURP_LAST_TIME)//5 seconds period
		{
			cDelay8Burp = 0;
			AlarmStatus.alarm.SHORT8 = 0;
			AlarmStatus.alarm.OCP_BURP_8 = 0;
		}
	}
}

/**
*@name: OCP_Check
*@description: check the OCP status(IO check)
*@params: none
*@return: none
*/
static void OCP_Process(void)
{
	OCP_Process1();
	OCP_Process2();
	OCP_Process3();
	OCP_Process4();
	OCP_Process5();
	OCP_Process6();
	OCP_Process7();
	OCP_Process8();
}

/**
*@name: Output_Status_Check
*@description: check the output status(IO check)
*@params: none
*@return: none
*/
static void Output_Status_Check(void)
{
    if(V1_OK == 1)//output error checking
	{
		v1_ok_H++;
	}
	else
	{
		v1_ok_L++;
	}
	if(V2_OK == 1)
	{
		v2_ok_H++;
	}
	else
	{
		v2_ok_L++;
	}
	if(V3_OK == 1)
	{
		v3_ok_H++;
	}
	else
	{
		v3_ok_L++;
	}
	if(V4_OK == 1)
	{
		v4_ok_H++;
	}
	else
	{
		v4_ok_L++;
	}
	if(V5_OK == 1)
	{
		v5_ok_H++;
	}
	else
	{
		v5_ok_L++;
	}	
	if(V6_OK == 1)
	{
		v6_ok_H++;
	}
	else
	{
		v6_ok_L++;
	}
	if(V7_OK == 1)
	{
		v7_ok_H++;
	}
	else
	{
		v7_ok_L++;
	}
	if(V8_OK == 1)
	{
		v8_ok_H++;
	}
	else
	{
		v8_ok_L++;
	}
	
	if(out_err_filter_cnt>=IO_FILTER_CNT)
	{
		if(v1_ok_H>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.OUT1_ERROR==1)
        {
			AlarmStatus.alarm.OUT1_ERROR=0;
        }
		else if(v1_ok_L>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.OUT1_ERROR==0)
        {
			AlarmStatus.alarm.OUT1_ERROR=1;
        } 
		if(v2_ok_H>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.OUT2_ERROR==1)
        {
			AlarmStatus.alarm.OUT2_ERROR=0;
        }		
		else if(v2_ok_L>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.OUT2_ERROR==0)
        {
			AlarmStatus.alarm.OUT2_ERROR=1;
        }
        if(v3_ok_H>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.OUT3_ERROR==1)
        {
			AlarmStatus.alarm.OUT3_ERROR=0;
        }
		else if(v3_ok_L>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.OUT3_ERROR==0)
        {
			AlarmStatus.alarm.OUT3_ERROR=1;
        }
		if(v4_ok_H>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.OUT4_ERROR==1)
        {
			AlarmStatus.alarm.OUT4_ERROR=0;
        }        
		else if(v4_ok_L>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.OUT4_ERROR==0)
        {
			AlarmStatus.alarm.OUT4_ERROR=1;
        }
		if(v5_ok_H>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.OUT5_ERROR==1)
        {
			AlarmStatus.alarm.OUT5_ERROR=0;
        }
		else if(v5_ok_L>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.OUT5_ERROR==0)
        {
			AlarmStatus.alarm.OUT5_ERROR=1;
        }
		if(v6_ok_H>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.OUT6_ERROR==1)
        {
			AlarmStatus.alarm.OUT6_ERROR=0;
        }		
		else if(v6_ok_L>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.OUT6_ERROR==0)
        {
			AlarmStatus.alarm.OUT6_ERROR=1;
        }
        if(v7_ok_H>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.OUT7_ERROR==1)
        {
			AlarmStatus.alarm.OUT7_ERROR=0;
        }
		else if(v7_ok_L>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.OUT7_ERROR==0)
        {
			AlarmStatus.alarm.OUT7_ERROR=1;
        }		
		if(v8_ok_H>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.OUT8_ERROR==1)
        {
			AlarmStatus.alarm.OUT8_ERROR=0;
        }        
		else if(v8_ok_L>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.OUT8_ERROR==0)
        {
			AlarmStatus.alarm.OUT8_ERROR=1;
        }
		out_err_filter_cnt=0;
		v1_ok_H=0;
		v1_ok_L=0;
		v2_ok_H=0;
		v2_ok_L=0;
		v3_ok_H=0;
		v3_ok_L=0;
		v4_ok_H=0;
		v4_ok_L=0;
		v5_ok_H=0;
		v5_ok_L=0;
		v6_ok_H=0;
		v6_ok_L=0;
		v7_ok_H=0;
		v7_ok_L=0;
		v8_ok_H=0;
		v8_ok_L=0;
	}
	else
	{
		out_err_filter_cnt++;
	}	
}

/**
*@name: Output_Manager
*@description: IO control according to the state flags
			   Here we just turn ON/OFF the eight outputs respectively.
*@params: none
*@return: none
*/
static void Output_Manager(void)
{
	//If the input is abnormal or the OTP is set, we turn OFF all outputs.
	if((AlarmStatus.alarm.VIN_STATUS_ERR == 0) && (AlarmStatus.alarm.OTP == 0))
	{
		/*
		If there is no OCP, turn ON the output directly.
		Once OCP occurs, we turn OFF the outpu for about 10 second, and then turn ON it for about 50-80 milli-seconds.
		Unless otherwise stated, other outputs have the same mechanism as the first channel.
		*/
		if((AlarmStatus.alarm.OCP_BURP_1 == 0) && (EnableOpen.open.PS1_OPEN == 1))
		{
			PS1_ON();
			cDelay1Burp = 0;
		}
		else
		{
			PS1_OFF();
			cBurpOnDelay1 = 5;
		}
		if((AlarmStatus.alarm.OCP_BURP_2 == 0) && (EnableOpen.open.PS2_OPEN == 1))
		{
			PS2_ON();
			cDelay2Burp = 0;
		}
		else
		{
			PS2_OFF();
			cBurpOnDelay2 = 5;
		}
		if((AlarmStatus.alarm.OCP_BURP_3 == 0) && (EnableOpen.open.PS3_OPEN == 1))
		{
			PS3_ON();
			cDelay3Burp = 0;
		}
		else
		{
			PS3_OFF();
			cBurpOnDelay3 = 5;
		}
		if((AlarmStatus.alarm.OCP_BURP_4 == 0) && (EnableOpen.open.PS4_OPEN == 1))
		{
			PS4_ON();
			cDelay4Burp = 0;
		}
		else
		{
			PS4_OFF();
			cBurpOnDelay4 = 5;
		}
		if((AlarmStatus.alarm.OCP_BURP_5 == 0) && (EnableOpen.open.PS5_OPEN == 1))
		{
			PS5_ON();
			cDelay5Burp = 0;
		}
		else
		{
			PS5_OFF();
			cBurpOnDelay5 = 5;
		}
		if((AlarmStatus.alarm.OCP_BURP_6 == 0) && (EnableOpen.open.PS6_OPEN == 1))
		{
			PS6_ON();
			cDelay6Burp = 0;
		}
		else
		{
			PS6_OFF();
			cBurpOnDelay6 = 5;
		}
		if((AlarmStatus.alarm.OCP_BURP_7 == 0) && (EnableOpen.open.PS7_OPEN == 1))
		{
			PS7_ON();
			cDelay7Burp = 0;
		}
		else
		{
			PS7_OFF();
			cBurpOnDelay7 = 5;
		}
		if((AlarmStatus.alarm.OCP_BURP_8 == 0) && (EnableOpen.open.PS8_OPEN == 1))
		{
			PS8_ON();
			cDelay8Burp = 0;
		}
		else
		{
			PS8_OFF();
			cBurpOnDelay8 = 5;
		}
	}
	else
	{
		PS1_OFF();
		PS2_OFF();
		PS3_OFF();
		PS4_OFF();
		PS5_OFF();
		PS6_OFF();
		PS7_OFF();
		PS8_OFF();
	}
}


/**
*@name: PS_OnOff
*@description: turn ON/OFF all the channels			   
*@params: flag: 1: ON,0:OFF
*@return: none
*/
void PS_OnOff(uint8_t flag)
{
	if(flag)
	{
		PS1_ON();
		PS2_ON();
		PS3_ON();
		PS4_ON();
		PS5_ON();
		PS6_ON();
		PS7_ON();
		PS8_ON();
	}
	else
	{
		PS1_OFF();
		PS2_OFF();
		PS3_OFF();
		PS4_OFF();
		PS5_OFF();
		PS6_OFF();
		PS7_OFF();
		PS8_OFF();
	}
}

/**
*@name: ADC_Status_Check
*@description: ADC filter, the input voltage and OTP check		   
*@params: none
*@return: none
*/
static void ADC_Status_Check(void)
{
	if(vdc_ad_value<=VDC_UV_OFF_AD)	//DC under/over voltage filter
		vdc_uvp_off++;
	if(vdc_ad_value>=VDC_UV_ON_AD)
		vdc_uvp_recovered++;
	if(vdc_ad_value>=VDC_OV_OFF_AD)
		vdc_ovp_off++;
	if(vdc_ad_value<=VDC_OV_ON_AD)
		vdc_ovp_recovered++;
	
	if(otp_ad_value>=OTP_OFF_AD)	//OTP
		otp_off++;
	if(otp_ad_value<=OTP_RECOVER_AD)
		otp_recovered++;
	
	if(adc_filter_cnt>=IO_FILTER_CNT)
	{
		if(vdc_uvp_off>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.VDC_UVP==0)	//VDC
			AlarmStatus.alarm.VDC_UVP=1;
		if(vdc_uvp_recovered>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.VDC_UVP==1)
			AlarmStatus.alarm.VDC_UVP=0;
		
        if(vdc_ovp_off>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.VDC_OVP==0)
			AlarmStatus.alarm.VDC_OVP=1;
		if(vdc_ovp_recovered>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.VDC_OVP==1)
			AlarmStatus.alarm.VDC_OVP=0;
		
        if(otp_off>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.OTP==0)	//OTP
			AlarmStatus.alarm.OTP=1;
		if(otp_recovered>=IO_FILTER_VALID_CNT && AlarmStatus.alarm.OTP==1)
			AlarmStatus.alarm.OTP=0;
        
        if(AlarmStatus.alarm.VDC_OVP==0 && AlarmStatus.alarm.VDC_UVP==0)
        {
            AlarmStatus.alarm.VIN_STATUS_ERR=0;
        }
        else
        {
            AlarmStatus.alarm.VIN_STATUS_ERR=1;
        }
		adc_filter_cnt=0;
		vdc_uvp_off=0;
		vdc_uvp_recovered=0;
		vdc_ovp_off=0;
		vdc_ovp_recovered=0;		
		otp_off=0;
		otp_recovered=0;
	}
	else
	{
		adc_filter_cnt++;
	}
}

/**
*@name: Process_1MS
*@description: 1 milli-second timeout process
*@params: none
*@return: none
*/
static void Process_1MS(void)
{
	if(Flag_1ms == 0)
	{
		return;
	}		
	Flag_1ms = 0;
	Output_Status_Check();
    ADC_Status_Check();
}

/**
*@name: Process_10MS
*@description: 10 milli-seconds timeout process used to process the OCP check
*@params: none
*@return: none
*/
static void Process_10MS(void)
{
	if(cDelay_10ms >= 10)
	{
		cDelay_10ms = 0;
		if(cBurpOnDelay1!=0) cBurpOnDelay1--;
		if(cBurpOnDelay2!=0) cBurpOnDelay2--;
		if(cBurpOnDelay3!=0) cBurpOnDelay3--;
		if(cBurpOnDelay4!=0) cBurpOnDelay4--;
		if(cBurpOnDelay5!=0) cBurpOnDelay5--;
		if(cBurpOnDelay6!=0) cBurpOnDelay6--;
		if(cBurpOnDelay7!=0) cBurpOnDelay7--;
		if(cBurpOnDelay8!=0) cBurpOnDelay8--;
		
		//once in OCP state we count-up
		if(AlarmStatus.alarm.SHORT1 && cDelay1Burp < 1200) cDelay1Burp++;
		if(AlarmStatus.alarm.SHORT2 && cDelay2Burp < 1200) cDelay2Burp++;
		if(AlarmStatus.alarm.SHORT3 && cDelay3Burp < 1200) cDelay3Burp++;
		if(AlarmStatus.alarm.SHORT4 && cDelay4Burp < 1200) cDelay4Burp++;
		if(AlarmStatus.alarm.SHORT5 && cDelay5Burp < 1200) cDelay5Burp++;
		if(AlarmStatus.alarm.SHORT6 && cDelay6Burp < 1200) cDelay6Burp++;
		if(AlarmStatus.alarm.SHORT7 && cDelay7Burp < 1200) cDelay7Burp++;
		if(AlarmStatus.alarm.SHORT8 && cDelay8Burp < 1200) cDelay8Burp++;
		
		if(cBurpOn1Flag < 10) ++cBurpOn1Flag;
		if(cBurpOn2Flag < 10) ++cBurpOn2Flag;
		if(cBurpOn3Flag < 10) ++cBurpOn3Flag;
		if(cBurpOn4Flag < 10) ++cBurpOn4Flag;
		if(cBurpOn5Flag < 10) ++cBurpOn5Flag;
		if(cBurpOn6Flag < 10) ++cBurpOn6Flag;
		if(cBurpOn7Flag < 10) ++cBurpOn7Flag;
		if(cBurpOn8Flag < 10) ++cBurpOn8Flag;
	}
}

/**
 * @brief   Main program
 *          The system clock frequency and PLL are all configured in the function SystemInit which is called in the startup_n32g032.s file.
 *			Therefore, we don't need to explicitly call the SystemInit function.
 */
int main(void)
{	
	//SystemInit();
    RCC_Configuration();
    GPIO_Configuration();
    ADC_Initial();
	#if IIC_MODE == 1	
	I2C_Master_Init();
	#else
	I2C1_Initial();
	I2C2_Initial();
	#endif
	TIM3_Configuration();
    //TIM6_Configuration();	
	EnableOpen.open.PS1_OPEN=1;//enable to be turn ON by the upper machine
	EnableOpen.open.PS2_OPEN=1;
	EnableOpen.open.PS3_OPEN=1;
	EnableOpen.open.PS4_OPEN=1;
	EnableOpen.open.PS5_OPEN=1;
	EnableOpen.open.PS6_OPEN=1;
	EnableOpen.open.PS7_OPEN=1;
	EnableOpen.open.PS8_OPEN=1;
    AlarmStatus.alarm.VIN_STATUS_ERR=1;
	while(run_time < START_UP_DELAY);
	run_time = 0;
	IWDG_Init();

#if 0
    /* Test on channel1 transfer complete flag */
    while(!DMA_GetFlagStatus(DMA_FLAG_TC1,DMA));
    /* Clear channel1 transfer complete flag */
    DMA_ClearFlag(DMA_FLAG_TC1,DMA);
    /* TIM1 counter disable */
    TIM_Enable(TIM1, DISABLE);
#endif

    while (1)
    {
		ADC_Process();
		Process_1MS();
		Process_10MS();
		OCP_Process();
		Output_Manager();
        Process_I2C2();
        IWDG_ReloadKey();
    }
	
	//return 0;//unreachable statement
}

/**
 * @brief  Configures the different system clocks.
 */
static void RCC_Configuration(void)
{
	// PCLK1 = HCLK/4, configure the clock of APB1 and times uses the prescaled APB1
    RCC_ConfigPclk1(RCC_HCLK_DIV4);
	
    // Enable peripheral clocks ------------------------------------------------
    // Enable TIM1 clocks
    //RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_TIM1, ENABLE);
    //Enable DMA clocks
    //RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA, ENABLE);

    //Enable GPIO clocks
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_GPIOB |RCC_APB2_PERIPH_GPIOC|RCC_APB2_PERIPH_GPIOF, ENABLE);
    //Enable ADC clocks
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC ,ENABLE);

    //RCC_ADCHCLK_DIV16
    ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB, RCC_ADCHCLK_DIV16);

    //enable ADC1M clock
    //RCC_EnableHsi(ENABLE);
    RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSE, RCC_ADC1MCLK_DIV8);
	
	//enable USART1 clock
	RCC_EnableAPB2PeriphClk(USARTy_GPIO_CLK, ENABLE);
	RCC_EnableAPB2PeriphClk(USARTy_CLK, ENABLE);
	
	//TIM3 and TIM clock enable
    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM3, ENABLE);
    //RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM6, ENABLE);
}

/**
*@name: GPIO_Configuration
*@description: GPIO configuration
*@params: none
*@return: none
*/
static void GPIO_Configuration(void)
{
    GPIO_InitType GPIO_InitStructure;

    GPIO_InitStruct(&GPIO_InitStructure);
    //Configure TIM1_CH2(PA9) as alternate function push-pull
    //GPIO_InitStructure.Pin        = GPIO_PIN_9; 
    //GPIO_InitStructure.GPIO_Current = GPIO_DC_LOW;
    //GPIO_InitStructure.GPIO_Mode  = GPIO_MODE_AF_PP;
    //GPIO_InitStructure.GPIO_Alternate = GPIO_AF2_TIM1;//alternate function
    //GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
	//************************************************************************************
	//		===================OFF1-OFF8=====================
    //		PB2,3,4,5,8,9,10 and PA15 are the output switches, corresponding to OFF1-OFF8
	//************************************************************************************
    GPIO_InitStructure.Pin       = GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);	
	GPIO_InitStructure.Pin       = GPIO_PIN_15;
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
	
	//************************************************************************************
	//		===================V1_OK-V8_OK=====================
    //		PC13,PC14,PC15-->V1_OK, V2_OK, V3_OK,
	//		PF2,PF6,PF7-->V4_OK, V7_OK, V5_OK
	//		PA13, PA14-->V8_OK, V6_OK
	//************************************************************************************
	//When IC starts up, pin PF2 is used as BOOT0 and the default mode is pull-down. Here we regard it as a normal GPIO.
	GPIO_InitStructure.Pin       = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
    GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure);
	GPIO_InitStructure.Pin       = GPIO_PIN_2|GPIO_PIN_6|GPIO_PIN_7;	
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
    GPIO_InitPeripheral(GPIOF, &GPIO_InitStructure);
	
	//============ PF7 as LED test pin =================
	//GPIO_InitStructure.Pin       = GPIO_PIN_7;
    //GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
	//GPIO_InitStructure.GPIO_Speed=GPIO_SPEED_HIGH;
	//GPIO_InitStructure.GPIO_Current=GPIO_DC_HIGH;
    //GPIO_InitPeripheral(GPIOF, &GPIO_InitStructure);
	
	//==========Mask PA13 and PA14 temporarily, for the two pins are the burning pin==========
	//GPIO_InitStructure.Pin       = GPIO_PIN_13|GPIO_PIN_14;
    //GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
    //GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);	
	
	//************************************************************************************
	//		===================OCP1-OCP8=====================
    //		PB11-PB15-->OCP1-OCP5	
	//		PA8, PA11, PA12-->OCP6-OCP8
	//************************************************************************************
	//PB11-PB15, OCP1-OCP5,PA8,PA11,PA12, OCP6-OCP8
	GPIO_InitStructure.Pin       = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
    GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
	GPIO_InitStructure.Pin       = GPIO_PIN_8 | GPIO_PIN_11 | GPIO_PIN_12;
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
	PS_OnOff(0);
}

#ifdef USE_FULL_ASSERT

/**
 * @brief  Reports the name of the source file and the source line number
 *         where the assert_param error has occurred.
 * @param file pointer to the source file name
 * @param line assert_param error line source number
 */
void assert_failed(const uint8_t* expr, const uint8_t* file, uint32_t line)
{
    /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

    /* Infinite loop */
    while (1)
    {
    }
}

#endif

2、main.h

/*****************************************************************************
 * Copyright (c) 2019, Nations Technologies Inc.
 *
 * All rights reserved.
 * ****************************************************************************
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the disclaimer below.
 *
 * Nations' name may not be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ****************************************************************************/

/**
 * @file main.h
 * @author Nations Solution Team
 * @version v1.0.0
 *
 * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved.
 */
#ifndef __MAIN_H__
#define __MAIN_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "n32g031.h"
#include "usart.h"
#include "adc.h"
#include "timer.h"
#include "iwdg.h"
#if IIC_MODE == 1
#include "i2c_master.h"
#else
#include "i2c_slave.h"
#endif

#define     START_UP_DELAY          3000
#define		BURP_LAST_TIME			500		//hiccup OFF duration(5000 ms)
#define     BURP_LAST_TIME2         1000   	//10 seconds interval for hiccup
#define		BURP_PS_ON_TIME			80		//hiccup ON duration(50ms)
#define		IO_FILTER_CNT			20		//IO filter count
#define		IO_FILTER_VALID_CNT		20		//IO filter valid count
#define		IIC_MODE				0		//I2C mode,0: slave, 1: master
#define 	__NULL 	((void*) 0)

/*
===========================================================================

								OFF1-OFF8

===========================================================================
*/
#define		PS_ON_OFF_GPIOx		GPIOB	//ON/OFF PORT1
#define		PS_ON_OFF_GPIOy		GPIOA	//ON/OFF PORT2
#define		OCP_GPIOx			GPIOB	//OCP PORT1
#define		OCP_GPIOy			GPIOA	//OCP PORT2
#define		VOUT_GPIOx			GPIOC	//OUTPUT_OK PORT1
#define		VOUT_GPIOy			GPIOF	//OUTPUT_OK PORT2
#define		VOUT_GPIOz			GPIOA	//OUTPUT_OK PORT3

#define		PS1_ON()			GPIO_ResetBits(PS_ON_OFF_GPIOx, GPIO_PIN_9)
#define		PS1_OFF()			GPIO_SetBits(PS_ON_OFF_GPIOx, GPIO_PIN_9)
#define		PS2_ON()			GPIO_ResetBits(PS_ON_OFF_GPIOx, GPIO_PIN_8)
#define		PS2_OFF()			GPIO_SetBits(PS_ON_OFF_GPIOx, GPIO_PIN_8)
#define		PS3_ON()			GPIO_ResetBits(PS_ON_OFF_GPIOx, GPIO_PIN_2)
#define		PS3_OFF()			GPIO_SetBits(PS_ON_OFF_GPIOx, GPIO_PIN_2)
#define		PS4_ON()			GPIO_ResetBits(PS_ON_OFF_GPIOx, GPIO_PIN_10)
#define		PS4_OFF()			GPIO_SetBits(PS_ON_OFF_GPIOx, GPIO_PIN_10)
#define		PS5_ON()			GPIO_ResetBits(PS_ON_OFF_GPIOx, GPIO_PIN_5)
#define		PS5_OFF()			GPIO_SetBits(PS_ON_OFF_GPIOx, GPIO_PIN_5)
#define		PS6_ON()			GPIO_ResetBits(PS_ON_OFF_GPIOx, GPIO_PIN_4)
#define		PS6_OFF()			GPIO_SetBits(PS_ON_OFF_GPIOx, GPIO_PIN_4)
#define		PS7_ON()			GPIO_ResetBits(PS_ON_OFF_GPIOx, GPIO_PIN_3)
#define		PS7_OFF()			GPIO_SetBits(PS_ON_OFF_GPIOx, GPIO_PIN_3)
#define		PS8_ON()			GPIO_ResetBits(PS_ON_OFF_GPIOy, GPIO_PIN_15)
#define		PS8_OFF()			GPIO_SetBits(PS_ON_OFF_GPIOy, GPIO_PIN_15)


#define		PS1_STATUS()		GPIO_ReadOutputDataBit(PS_ON_OFF_GPIOx, GPIO_PIN_9)
#define		PS2_STATUS()		GPIO_ReadOutputDataBit(PS_ON_OFF_GPIOx, GPIO_PIN_8)
#define		PS3_STATUS()		GPIO_ReadOutputDataBit(PS_ON_OFF_GPIOx, GPIO_PIN_2)
#define		PS4_STATUS()		GPIO_ReadOutputDataBit(PS_ON_OFF_GPIOx, GPIO_PIN_10)
#define		PS5_STATUS()		GPIO_ReadOutputDataBit(PS_ON_OFF_GPIOx, GPIO_PIN_5)
#define		PS6_STATUS()		GPIO_ReadOutputDataBit(PS_ON_OFF_GPIOx, GPIO_PIN_4)
#define		PS7_STATUS()		GPIO_ReadOutputDataBit(PS_ON_OFF_GPIOx, GPIO_PIN_3)
#define		PS8_STATUS()		GPIO_ReadOutputDataBit(PS_ON_OFF_GPIOy, GPIO_PIN_15)

/*
===========================================================================

							OCP1-OCP8

===========================================================================
*/
#define		OCP1				GPIO_ReadInputDataBit(OCP_GPIOx, GPIO_PIN_11)
#define		OCP2				GPIO_ReadInputDataBit(OCP_GPIOx, GPIO_PIN_12)
#define		OCP3				GPIO_ReadInputDataBit(OCP_GPIOx, GPIO_PIN_13)
#define		OCP4				GPIO_ReadInputDataBit(OCP_GPIOx, GPIO_PIN_14)
#define		OCP5				GPIO_ReadInputDataBit(OCP_GPIOx, GPIO_PIN_15)
#define		OCP6				GPIO_ReadInputDataBit(OCP_GPIOy, GPIO_PIN_8)
#define		OCP7				GPIO_ReadInputDataBit(OCP_GPIOy, GPIO_PIN_11)
#define		OCP8				GPIO_ReadInputDataBit(OCP_GPIOy, GPIO_PIN_12)

/*
===========================================================================

								V1_OK-V8_OK

===========================================================================
*/
#define		V1_OK				GPIO_ReadInputDataBit(VOUT_GPIOx, GPIO_PIN_13)
#define		V2_OK				GPIO_ReadInputDataBit(VOUT_GPIOx, GPIO_PIN_14)
#define		V3_OK				GPIO_ReadInputDataBit(VOUT_GPIOx, GPIO_PIN_15)
#define		V4_OK				GPIO_ReadInputDataBit(VOUT_GPIOy, GPIO_PIN_2)
#define		V5_OK				GPIO_ReadInputDataBit(VOUT_GPIOy, GPIO_PIN_7)
#define		V6_OK				GPIO_ReadInputDataBit(VOUT_GPIOz, GPIO_PIN_14)
#define		V7_OK				GPIO_ReadInputDataBit(VOUT_GPIOy, GPIO_PIN_6)
#define		V8_OK				GPIO_ReadInputDataBit(VOUT_GPIOz, GPIO_PIN_13)

struct ALARM{
	unsigned	SHORT1							: 1;//OCP flag
	unsigned	SHORT2							: 1;
	unsigned	SHORT3							: 1;
	unsigned	SHORT4							: 1;
	unsigned	SHORT5							: 1;
	unsigned	SHORT6							: 1;
	unsigned	SHORT7							: 1;
	unsigned	SHORT8							: 1;	
		
		
	unsigned	OUT1_ERROR						: 1;//output error
	unsigned	OUT2_ERROR						: 1;
	unsigned	OUT3_ERROR						: 1;
	unsigned	OUT4_ERROR						: 1;
	unsigned	OUT5_ERROR						: 1;
	unsigned	OUT6_ERROR						: 1;
	unsigned	OUT7_ERROR						: 1;
	unsigned	OUT8_ERROR						: 1;
		
		
	//unsigned	PSON_1							: 1; //switch status
	//unsigned	PSON_2							: 1;
	//unsigned	PSON_3							: 1;
	//unsigned	PSON_4							: 1;
	//unsigned	PSON_5							: 1;
	//unsigned	PSON_6							: 1;
	//unsigned	PSON_7							: 1;
	//unsigned	PSON_8							: 1;
	
	unsigned	OCP_BURP_1						: 1; //OCP and burp flag
	unsigned	OCP_BURP_2						: 1;
	unsigned	OCP_BURP_3						: 1;
	unsigned	OCP_BURP_4						: 1;
	unsigned	OCP_BURP_5						: 1;
	unsigned	OCP_BURP_6						: 1;
	unsigned	OCP_BURP_7						: 1;
	unsigned	OCP_BURP_8						: 1;
	
	unsigned	VIN_STATUS_ERR					: 1;//input voltage status
	unsigned	OTP								: 1;
	unsigned	VDC_UVP							: 1;
	unsigned	VDC_OVP							: 1;
	unsigned	I2C2_REQ_PROCESSED				: 1;//I2C2 processed
	unsigned	I2C2_NEW_REQ					: 1;//new request from master
	unsigned									: 1;
	unsigned									: 1;
};

union ALARM_STATUS_UNION {
	struct ALARM	alarm;
	uint32_t	allbits;
}; 

typedef union ALARM_STATUS_UNION ALARM_STATUS;


struct PS_OPEN_FLAG{
	unsigned	PS1_OPEN						: 1;//1-8通道是否要打开或关闭标识,由上位机设置,如果设置了该标识,也只能通过上位机修改
	unsigned	PS2_OPEN						: 1;
	unsigned	PS3_OPEN						: 1;
	unsigned	PS4_OPEN						: 1;
	unsigned	PS5_OPEN						: 1;
	unsigned	PS6_OPEN						: 1;
	unsigned	PS7_OPEN						: 1;
	unsigned	PS8_OPEN						: 1;	
		
		
	unsigned									: 1;
	unsigned									: 1;
	unsigned									: 1;
	unsigned									: 1;
	unsigned									: 1;
	unsigned									: 1;
	unsigned									: 1;
	unsigned									: 1;	
};

union PS_OPEN_UNION {
	struct PS_OPEN_FLAG	open;
	uint16_t	allbits;
}; 

typedef union PS_OPEN_UNION PS_Open;


typedef enum
{
    FAILED = 0,
    PASSED = !FAILED
} Status;

void PS_OnOff(uint8_t flag);

extern volatile PS_Open EnableOpen;
extern ALARM_STATUS AlarmStatus;
extern uint16_t  run_time;

#ifdef __cplusplus
}
#endif

#endif /* __MAIN_H__ */
/**
 * @}
 */

/**
 * @}
 */

/**
 * @}
 */

3、adc.c

#include "n32g031_adc.h"
#include "n32g031.h"
#include "adc.h"
#include 
#include 

#define 	CURRENT_RATE		((float)2457.0)//(4095*300/500)//rate between voltage and current, 3A corresponding to 3V

#define		SAMPLE_COUNT		64

uint8_t		sample_cnt=0; //sampled counter
uint8_t		sample_flag = 0; //sampling finished flag
uint8_t		channel=0; //channel to be sampled

uint8_t		adc_channels[ADC_CH_NUM]={IS1, IS2, IS3, IS4, IS5, IS6 ,IS7, IS8, VOS, TEMP};//all channels

uint32_t	is1_sample_sum  = 0; //accumulated AD value
uint16_t	is1_sample_value_filt = 0;//average AD values
uint16_t 	IS1_OUT;//the actual current, unit: mA

//Unless stated otherwise, the following variables are similar to that of IS1
uint32_t	is2_sample_sum  = 0;
uint16_t	is2_sample_value_filt = 0;
uint16_t	IS2_OUT;
uint32_t	is3_sample_sum  = 0;
uint16_t	is3_sample_value_filt = 0;
uint16_t	IS3_OUT;
uint32_t	is4_sample_sum  = 0;
uint16_t	is4_sample_value_filt = 0;
uint16_t	IS4_OUT;
uint32_t	is5_sample_sum  = 0;
uint16_t	is5_sample_value_filt = 0;
uint16_t	IS5_OUT;
uint32_t	is6_sample_sum  = 0;
uint16_t	is6_sample_value_filt = 0;
uint16_t	IS6_OUT;
uint32_t	is7_sample_sum  = 0;
uint16_t	is7_sample_value_filt = 0;
uint16_t	IS7_OUT;
uint32_t	is8_sample_sum  = 0;
uint16_t	is8_sample_value_filt = 0;
uint16_t	IS8_OUT;

uint32_t	vos_sample_sum  = 0;//input voltage
uint16_t	vdc_ad_value = 0;
uint16_t	VOS_OUT;
uint32_t	otp_sample_sum  = 0;//temperature
uint16_t	otp_ad_value = 0;
//signed int	TMP_OUT;
signed char	TMP_OUT;//the actual temperature rounded

//AD values corresponding to the the NTC temperature,(-40---125)
uint16_t TTC05104_ADArray[166]={0x5F,0x66,0x6E,0x75,0x7E,0x87,0x90,0x9A,0xA5,0xB0,
							0xBC,0xC8,0xD5,0xE3,0xF2,0x101,0x111,0x122,0x133,0x146,
							0x159,0x16D,0x182,0x198,0x1AF,0x1C7,0x1E0,0x1F9,0x214,0x22F,
							0x24C,0x26A,0x288,0x2A7,0x2C8,0x2E9,0x30C,0x32F,0x353,0x378,
							0x39E,0x3C5,0x3EC,0x414,0x43D,0x467,0x492,0x4BD,0x4E8,0x514,
							0x541,0x56E,0x59B,0x5C9,0x5F7,0x626,0x654,0x683,0x6B1,0x6E0,
							0x70F,0x73D,0x76C,0x79A,0x7C8,0x7F6,0x823,0x850,0x87D,0x8A9,
							0x8D5,0x900,0x92B,0x955,0x97F,0x9A8,0x9D0,0x9F8,0xA1F,0xA45,
							0xA6B,0xA90,0xAB4,0xAD7,0xAFA,0xB1C,0xB3D,0xB5E,0xB7D,0xB9C,
							0xBBB,0xBD8,0xBF5,0xC11,0xC2C,0xC47,0xC61,0xC7A,0xC92,0xCAA,
							0xCC2,0xCD8,0xCEE,0xD04,0xD18,0xD2C,0xD40,0xD53,0xD66,0xD77,
							0xD89,0xD9A,0xDAA,0xDBA,0xDC9,0xDD8,0xDE7,0xDF5,0xE03,0xE10,
							0xE1D,0xE29,0xE35,0xE41,0xE4C,0xE57,0xE62,0xE6C,0xE76,0xE80,
							0xE8A,0xE93,0xE9C,0xEA4,0xEAD,0xEB5,0xEBD,0xEC4,0xECC,0xED3,
							0xEDA,0xEE0,0xEE7,0xEED,0xEF3,0xEF9,0xEFF,0xF05,0xF0A,0xF0F,
							0xF15,0xF1A,0xF1E,0xF23,0xF28,0xF2C,0xF30,0xF35,0xF39,0xF3D,
							0xF40,0xF44,0xF48,0xF4B,0xF4F,0xF52};

/**
*@name: ADC_GPIO_Configuration
*@description: ADC GPIO configuration, they are: PA0-PA7 and PB0
*@params: none
*@return: none
*/
static void ADC_GPIO_Configuration(void)
{
    GPIO_InitType GPIO_InitStructure;

    GPIO_InitStruct(&GPIO_InitStructure);
    // Configure PA0-PA7 as analog input-->IS1-->IS8
    GPIO_InitStructure.Pin       = GPIO_PIN_0 | GPIO_PIN_1|GPIO_PIN_2 | GPIO_PIN_3|GPIO_PIN_4 | GPIO_PIN_5|GPIO_PIN_6 | GPIO_PIN_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_ANALOG;
    GPIO_InitPeripheral(ADC_GPIO1, &GPIO_InitStructure);
	
	// Configure PB0 AND PB1 as analog input-->input voltage and OTP
    GPIO_InitStructure.Pin       = GPIO_PIN_0|GPIO_PIN_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_ANALOG;
    GPIO_InitPeripheral(ADC_GPIO2, &GPIO_InitStructure);	
}

/**
 * @brief  Configures NVIC and Vector Table base location.
 */
void ADC_NVIC_Configuration(void)
{
    NVIC_InitType NVIC_InitStructure;

    //Configure and enable ADC interrupt
    NVIC_InitStructure.NVIC_IRQChannel                   = ADC_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority           = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}


/**
*@name: ADC_Initial
*@description: ADC initialization
*@params: none
*@return: none
*/
void ADC_Initial(void)
{
	ADC_InitType ADC_InitStructure;
	
	ADC_GPIO_Configuration();
	
    /* ADC configuration ------------------------------------------------------*/
    ADC_InitStructure.MultiChEn      = DISABLE;
    ADC_InitStructure.ContinueConvEn = DISABLE;
    ADC_InitStructure.ExtTrigSelect  = ADC_EXT_TRIGCONV_NONE;
    ADC_InitStructure.DatAlign       = ADC_DAT_ALIGN_R;
    ADC_InitStructure.ChsNumber      = 1;
    ADC_Init(ADC, &ADC_InitStructure);
	//ADC1 regular channel13 configuration
	//ADC_ConfigRegularChannel(ADC, ADC_CH_13_PC2, 1, ADC_SAMP_TIME_55CYCLES5);
	//Enable ADC DMA
	//ADC_EnableDMA(ADC, ENABLE);

    //Enable ADC
    ADC_Enable(ADC, ENABLE);
    
	// Check ADC Ready
    while(ADC_GetFlagStatusNew(ADC,ADC_FLAG_RDY) == RESET);
    while(ADC_GetFlagStatusNew(ADC,ADC_FLAG_PD_RDY));
	
	channel=IS1;
}


/**
*@name: ADC_GetData
*@description: get the converted AD value
*@params: ADC_Channel: channel to be converted
*@return: AD value we need
*/
uint16_t ADC_GetData(uint8_t ADC_Channel)
{
    uint16_t data;
	
    ADC_ConfigRegularChannel(ADC, ADC_Channel, 1, ADC_SAMP_TIME_56CYCLES5);
    // Start ADC Software Conversion
    ADC_EnableSoftwareStartConv(ADC,ENABLE);//start software conversion
    while(ADC_GetFlagStatus(ADC,ADC_FLAG_ENDC)==0)//wait for the conversion to be finished
	{
		
    }
    ADC_ClearFlag(ADC,ADC_FLAG_ENDC);//clear the end conversion flag
    ADC_ClearFlag(ADC,ADC_FLAG_STR);
    data = ADC_GetDat(ADC);
    
	return (data);
}

/**
*@name: Calc_IOUT
*@description: get the actual current according to the AD value(voltage), unit: mA
*@params: ad_value: AD value
*@return: the actual current value
*/
uint16_t Calc_IOUT(uint16_t ad_value)
{
	float val=0.00;	
	uint32_t l2=0;	
	
	l2 = ad_value;
	l2 *= 300;//3A:3V, multiplied by 100
	val=(float)l2;
	val /=CURRENT_RATE;
	if(l2 <= 0)
		return 0;
	else
		return (val*10);//mA
	
	//val=is1_sample_value_filt/ADCFS;		
	//IS1_OUT=val*5000;
}

/**
*@name: TTC05104_ADBinary_Search
*@description: get the index of the table NTC_ADArray according to the ADC value
			   order by ASC
*@params: ad_value: the sampled ADC value
*@return: the final AD value
*/
static uint8_t  TTC05104_ADBinary_Search(uint16_t ad_value)
{	
   int start=0; //start index
   int end = 165; //max index
   int mid = 0;  //the index we need
   while(start<=end)
   {
      mid=(start+end)/2;//get the middle index
	  if(mid==165) break;//the maximum index
      if(ad_value==TTC05104_ADArray[mid]) break;  //we get the right index  
      if((ad_value>TTC05104_ADArray[mid])&&(ad_valueTTC05104_ADArray[mid])  //the index we need is in the second part
		start = mid+1; 
		
      else if(ad_valueSAMPLE_COUNT)
				{
					sample_cnt = 0;
					is1_sample_value_filt=is1_sample_sum>>6;//get the average AD value
					is1_sample_sum = 0;
					channel = IS2;              //next channel
				}					
				break;
			}            
			case IS2:
			{
                ad_data=ADC_GetData(IS2);                
                is2_sample_sum+=ad_data;
				if(++sample_cnt>SAMPLE_COUNT)
				{
					sample_cnt = 0;
					is2_sample_value_filt=is2_sample_sum>>6;
					is2_sample_sum = 0;
					channel = IS3;
				}					
				break;
			}
			case IS3:
			{
                ad_data=ADC_GetData(IS3);                
                is3_sample_sum+=ad_data;
				if(++sample_cnt>SAMPLE_COUNT)
				{
					sample_cnt = 0;
					is3_sample_value_filt=is3_sample_sum>>6;
					is3_sample_sum = 0;
					channel = IS4;
				}					
				break;
			}
			case IS4:
			{
                ad_data=ADC_GetData(IS4);                
                is4_sample_sum+=ad_data;
				if(++sample_cnt>SAMPLE_COUNT)
				{
					sample_cnt = 0;
					is4_sample_value_filt=is4_sample_sum>>6;
					is4_sample_sum = 0;
					channel = IS5;
				}					
				break;
			}
			case IS5:
			{
                ad_data=ADC_GetData(IS5);                
                is5_sample_sum+=ad_data;
				if(++sample_cnt>SAMPLE_COUNT)
				{
					sample_cnt = 0;
					is5_sample_value_filt=is5_sample_sum>>6;
					is5_sample_sum = 0;
					channel = IS6;
				}					
				break;
			}
			case IS6:
			{
                ad_data=ADC_GetData(IS6);                
                is6_sample_sum+=ad_data;
				if(++sample_cnt>SAMPLE_COUNT)
				{
					sample_cnt = 0;
					is6_sample_value_filt=is6_sample_sum>>6;
					is6_sample_sum = 0;
					channel = IS7;
				}					
				break;
			}
			case IS7:
			{
                ad_data=ADC_GetData(IS7);                
                is7_sample_sum+=ad_data;
				if(++sample_cnt>SAMPLE_COUNT)
				{
					sample_cnt = 0;
					is7_sample_value_filt=is7_sample_sum>>6;
					is7_sample_sum = 0;
					channel = IS8;
				}					
				break;
			}
			case IS8:
			{
                ad_data=ADC_GetData(IS8);                
                is8_sample_sum+=ad_data;
				if(++sample_cnt>SAMPLE_COUNT)
				{
					sample_cnt = 0;
					is8_sample_value_filt=is8_sample_sum>>6;
					is8_sample_sum = 0;
					channel = TEMP;
				}					
				break;
			}
			case TEMP:
			{
                ad_data=ADC_GetData(TEMP);                
                otp_sample_sum+=ad_data;
				if(++sample_cnt>SAMPLE_COUNT)
				{
					sample_cnt = 0;
					otp_ad_value=otp_sample_sum>>6;
					otp_sample_sum = 0;
					channel = VOS;
				}					
				break;
			}
			case VOS:
			{
                ad_data=ADC_GetData(VOS);                
                vos_sample_sum+=ad_data;
				if(++sample_cnt>SAMPLE_COUNT)
				{
					sample_cnt = 0;
					vdc_ad_value=vos_sample_sum>>6;
					vos_sample_sum = 0;					
					sample_flag = 1;//sampleing finished flag
					channel = IS1;
				}					
				break;
			}
			default:
			{
				channel=IS1;
				sample_cnt = 0;
				is1_sample_sum=0;
				is2_sample_sum=0;
				is3_sample_sum=0;
				is4_sample_sum=0;
				is5_sample_sum=0;
				is6_sample_sum=0;
				is7_sample_sum=0;
				is8_sample_sum=0;
				vos_sample_sum=0;
				otp_sample_sum=0;
				break;
			}
		}
	}
}

4、adc.h

#ifndef __ADC_H__
#define __ADC_H__

#include "n32g031.h"

#define 	ADC_GPIO1      	GPIOA
#define		ADC_GPIO2		GPIOB
#define 	ADC_GPIO_CLK   	RCC_APB2_PERIPH_GPIOA

#define 	ADC_CH_NUM		10
#define 	IS1				ADC_CH_0_PA0
#define		IS2 			ADC_CH_1_PA1
#define		IS3 			ADC_CH_2_PA2
#define		IS4 			ADC_CH_3_PA3
#define		IS5 			ADC_CH_4_PA4
#define		IS6 			ADC_CH_5_PA5
#define		IS7 			ADC_CH_6_PA6
#define		IS8 			ADC_CH_7_PA7
#define 	VOS				ADC_CH_8_PB0
#define 	TEMP			ADC_CH_9_PB1

/*
#define		REF5V0			5.000		// 5V reference voltage
#define		Rup				100.0		// high resistor,kΩ
#define		Rdown			4.3			// low resistor,kΩ
#define		ADCFS			4095.0		// 12-bit ADC
#define		VIN40			40.0
#define		VIN70			70.0		
#define		VIN_MAX			(float)((1.0 + Rup/Rdown) * REF5V0)	//maximum input voltage: 78.5V
#define		VIN40_ADC		((uint16_t)(((VIN40)/(VIN_MAX)) * (ADCFS)))
#define		VIN70_ADC		((uint16_t)(((VIN70)/(VIN_MAX)) * (ADCFS)))
*/
/*
===========================================================================

					DC under/over voltage macros

===========================================================================
*/
#define			ADCFS					4095.0  //12-bit ADC maximum AD value
#define			ADCREF                  5.0     //5V reference voltage
#define			ADC_DIV_REF             (float)(ADCFS/ADCREF)
	
#define         VIN_DIV_RUP				(100.0) //up and down resistors
#define         VIN_DIV_RLOW			4.3
#define         VIN_SENSE_FULLSCALE     ((1.0 + VIN_DIV_RUP/VIN_DIV_RLOW) * ADCREF)	//Maximum input voltage 105V
#define         VIN_DIV_GAIN			((float)(VIN_DIV_RLOW/(VIN_DIV_RLOW + VIN_DIV_RUP)))//gain: 4.3/(4.3+100)
#define         VDC_UV_OFF				41.0     //DC under voltage alarm
#define         VDC_UV_ON				45.0     //DC under voltage recovered
#define         VDC_OV_OFF				65.0     //DC over voltage alarm
#define         VDC_OV_ON				60.0     //DC over voltage recovered
#define         VDC_UV_OFF_AD			(uint16_t)(VDC_UV_OFF * VIN_DIV_GAIN * ADC_DIV_REF)
#define         VDC_UV_ON_AD			(uint16_t)(VDC_UV_ON * VIN_DIV_GAIN * ADC_DIV_REF)
#define         VDC_OV_OFF_AD			(uint16_t)(VDC_OV_OFF * VIN_DIV_GAIN * ADC_DIV_REF)
#define         VDC_OV_ON_AD			(uint16_t)(VDC_OV_ON * VIN_DIV_GAIN * ADC_DIV_REF)

/*
===========================================================================

					OTP macros

===========================================================================
*/
#define         OTP_OFF					3.0	//NTC=5.6K, temperature: 100
#define         OTP_RECOVER				2.5 //NTC=10K, temperature: 85
#define			OTP_OFF_AD				3722//90C, (((uint16_t)(((OTP1_OFF)/(ADCREF)) * (ADCFS)))
#define			OTP_RECOVER_AD			3613//80C, (((OTP1_RECOVER)/(ADCREF)) * (ADCFS)))


/*
===========================================================================

					Current calculating macros

===========================================================================
*/
#define         IS_RESISTOR             	0.03 //the current sampling resistor is 30mR
#define         IS_GAIN                 	(33.0/1)//33K/1K
#define			CURRENT_CALCULATE(ad)		((uint16_t)(((float)ad)/ADCFS*ADCREF/IS_GAIN/IS_RESISTOR*1000))//multiplied by 1000 means the result is uA

/*
===========================================================================

					external members

===========================================================================
*/
extern 		uint16_t        IS1_OUT;
extern 		uint16_t        IS2_OUT;
extern 		uint16_t        IS3_OUT;
extern 		uint16_t        IS4_OUT;
extern 		uint16_t        IS5_OUT;
extern 		uint16_t        IS6_OUT;
extern 		uint16_t        IS7_OUT;
extern 		uint16_t        IS8_OUT;
extern 		uint16_t		VOS_OUT;
//extern		signed int		TMP_OUT;
extern		signed char		TMP_OUT;
extern 		uint16_t		vdc_ad_value;
extern 		uint16_t		otp_ad_value;

static void ADC_GPIO_Configuration(void);
void ADC_Initial(void);
void ADC_Process(void);
void ADC_Sample(void);
uint16_t ADC_GetData(uint8_t ADC_Channel);
uint16_t Calc_IOUT(uint16_t ad_value);
signed char Get_Temp(void);

#endif

5、usart.c

#include "n32g031.h"
#include "n32g031_usart.h"
#include "usart.h"
#include "main.h"
#include 
#include "crc16.h"

struct	UART_Data_Struct	UART1_STRUCT;

//#define 	__NULL 	((void*) 0)

/*
======================================================

			RS485 related macros

======================================================
*/
#define		RS485_GPIOx_CLK		RCC_APB2_PERIPH_GPIOB
#define		RS485_GPIO_PIN		GPIO_PIN_10
#define 	RS485_GPIOx        	GPIOB
#define		RS485_L()			GPIO_ResetBits(RS485_GPIOx, RS485_GPIO_PIN)
#define		RS485_H()			GPIO_SetBits(RS485_GPIOx, RS485_GPIO_PIN)

uint8_t		RS485_Delay;		//the switching time between transmit mode and receive mode of RS485
uint8_t		object_num=0;		//object numbers

const char module_type[]="CHINA TELECOM PSU";//module name
const char software_version[]="V1.0.1";//software version
volatile uint8_t rcv_timeout=0;


/**
*@name: RS485_Configuration
*@description: RS485 configuration which is not called
*@params: none
*@return: none
*/
void RS485_Configuration(void)
{
	GPIO_InitType GPIO_InitStructure;
	RCC_EnableAPB2PeriphClk(RS485_GPIOx_CLK, ENABLE);

    /* -2- Configure GPIOx_PIN in output push-pull mode */
    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStructure.Pin = RS485_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_HIGH;
    GPIO_InitPeripheral(RS485_GPIOx, &GPIO_InitStructure);
	GPIO_ResetBits(RS485_GPIOx, RS485_GPIO_PIN);
}


/**
 * @brief  Configures the different GPIO ports of USART.
 */
void USART_Configuration(void)
{
    GPIO_InitType GPIO_InitStructure;
	USART_InitType USART_InitStructure;

    //Initialize GPIO_InitStructure
    GPIO_InitStruct(&GPIO_InitStructure);
   
    //Configure USARTy Tx as alternate function push-pull
    GPIO_InitStructure.Pin            = USARTy_TxPin;    
    GPIO_InitStructure.GPIO_Mode      = GPIO_MODE_AF_PP;
    GPIO_InitStructure.GPIO_Alternate = USARTy_Tx_GPIO_AF;//alternate function
    GPIO_InitPeripheral(USARTy_GPIO, &GPIO_InitStructure);

    //Configure USARTx Rx as alternate function push-pull
    GPIO_InitStructure.Pin            = USARTy_RxPin;
    GPIO_InitStructure.GPIO_Alternate = USARTy_Rx_GPIO_AF;//alternate function
    GPIO_InitPeripheral(USARTy_GPIO, &GPIO_InitStructure);

	USART_NVIC_Configuration();
	
	 //USARTy and USARTz configuration ------------------------------------------------------
    USART_InitStructure.BaudRate            = USART_BAUD_RATE;
    USART_InitStructure.WordLength          = USART_WL_8B;
    USART_InitStructure.StopBits            = USART_STPB_1;
    USART_InitStructure.Parity              = USART_PE_NO;
    USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
    USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;

    //Configure USART1
    USART_Init(USARTy, &USART_InitStructure);

    //Enable USARTy Receive and Transmit interrupts
    USART_ConfigInt(USARTy, USART_INT_RXDNE, ENABLE);
    USART_ConfigInt(USARTy, USART_INT_TXDE, ENABLE);
	 USART_ConfigInt(USARTy, USART_INT_ERRF, ENABLE);
	//USART_ConfigInt(USARTy, USART_INT_IDLEF, ENABLE);

    //Enable the USART1
    USART_Enable(USARTy, ENABLE);
	
	UART1_STRUCT.R_InPtr = 0;
	UART1_STRUCT.R_Flag = 0;
    UART1_STRUCT.R_Detransferred_Ptr=0;
	UART1_STRUCT.R_DTSime = 125;
	UART1_STRUCT.T_Length = 0;
	UART1_STRUCT.T_OutPtr = 0;
    UART1_STRUCT.T_Transferred_OutPtr=0;
	UART1_STRUCT.T_Flag = 0;
	UART1_STRUCT.T_DTSime = 0;
	UART1_STRUCT.T_Time = 0;
	
	//RS485_L();//receive mode
	//RS485_Delay = 0;
}

/**
 * @brief  Configures the nested vectored interrupt controller.
 */
static void USART_NVIC_Configuration(void)
{
    NVIC_InitType NVIC_InitStructure;

    // Enable the USARTy Interrupt
    NVIC_InitStructure.NVIC_IRQChannel                   = USARTy_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority           = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}


/**
*@name: Analyze_Receive_Data
*@description: check the received frame
*@params: none
*@return: error code
*/
//uint16_t crc16_t=0;

static uint8_t Analyze_Receive_Data(void)
{
	uint16_t crc16=0;
	int8_t load_data_len=0;
	uint8_t len=0;
	uint8_t ttl_len=0;
	uint8_t *pos=__NULL;
	uint16_t i=0;	
	object_num=0;
	//ttl_len=0;load_data_len=0;	
	
	while(i0)
	{
		len=*pos;
		//if(len<4 || len>5)
        if(len!=4 && len!=5 && len!=23)//the fixed data length
		{
			//object_num=0;
			return (DATA_ERROR);
		}
		object_num++;
		load_data_len-=len;
		pos+=len;
		ttl_len+=len;
	}
	
	if(load_data_len!=0)
	{
		return (DATA_ERROR);
	}
	
	load_data_len=UART1_STRUCT.R_Detransferred_Ptr-DATA_EXCLUDED_LEN;
	if(load_data_len!=ttl_len)
	{
		return(DATA_ERROR);
	}
	/*
	if((UART1_STRUCT.R_Buffer[0] != SOI) || (UART1_STRUCT.R_Buffer[UART1_STRUCT.R_InPtr - 1] != EOI))
	{
		return(CONFINED_EXECUTED);
	}
	*/
		
	return(NORMAL);
}


/**
*@name: Get_OCP_Status
*@description: get the OCP status of the designated channel
*@params: channel: channel
*@return: 1: OCP, 0:OK
*/
uint8_t Get_OCP_Status(uint8_t channel)
{
	uint8_t result=0;
	
	switch(channel)
	{
		case 0:
			//result=OCP1;
			result=AlarmStatus.alarm.SHORT1;
			break;
		case 1:
			//result=OCP2;
			result=AlarmStatus.alarm.SHORT2;
			break;
		case 2:
			//result=OCP3;
			result=AlarmStatus.alarm.SHORT3;
			break;
		case 3:
			//result=OCP4;
			result=AlarmStatus.alarm.SHORT4;
			break;
		case 4:
			//result=OCP5;
			result=AlarmStatus.alarm.SHORT5;
			break;
		case 5:
			//result=OCP6;
			result=AlarmStatus.alarm.SHORT6;
			break;
		case 6:
			//result=OCP7;
			result=AlarmStatus.alarm.SHORT7;
			break;
		case 7:
			//result=OCP8;
			result=AlarmStatus.alarm.SHORT8;
			break;
		default:
			break;
	}
	
	return (result);
}

/**
*@name: Get_VOUT_Status
*@description: get the output status of the designated channel
*@params: channel: channel number
*@return: 0:OK,1:abnormal
*/
uint8_t Get_VOUT_Status(uint8_t channel)
{
	uint8_t result=0;
	
	switch(channel)
	{
		case 0:
			//result=V1_OK==1?0:1;
			result=AlarmStatus.alarm.OUT1_ERROR;
			break;
		case 1:
			//result=V2_OK==1?0:1;
			result=AlarmStatus.alarm.OUT2_ERROR;
			break;
		case 2:
			//result=V3_OK==1?0:1;
			result=AlarmStatus.alarm.OUT3_ERROR;
			break;
		case 3:
			//result=V4_OK==1?0:1;
			result=AlarmStatus.alarm.OUT4_ERROR;
			break;
		case 4:
			//result=V5_OK==1?0:1;
			result=AlarmStatus.alarm.OUT5_ERROR;
			break;
		case 5:
			//result=V6_OK==1?0:1;
			result=AlarmStatus.alarm.OUT6_ERROR;
			break;
		case 6:
			//result=V7_OK==1?0:1;
			result=AlarmStatus.alarm.OUT7_ERROR;
			break;
		case 7:
			//result=V8_OK==1?0:1;
			result=AlarmStatus.alarm.OUT8_ERROR;
			break;
		default:
			break;
	}
	
	return (result);
}

/**
*@name: Get_IOUT_Value
*@description: get the current value of the designated channel
*@params: channel: channel number
*@return: current value: mA
*/
//extern uint16_t is1_sample_value_filt;
uint16_t Get_IOUT_Value(uint8_t channel)
{
	uint16_t result=0;
	
	switch(channel)
	{
		case 0:			
			result=IS1_OUT;			
			break;
		case 1:
			result=IS2_OUT;
			break;
		case 2:
			result=IS3_OUT;
			break;
		case 3:
			result=IS4_OUT;
			break;
		case 4:
			result=IS5_OUT;
			break;
		case 5:
			result=IS6_OUT;
			break;
		case 6:
			result=IS7_OUT;
			break;
		case 7:
			result=IS8_OUT;
			break;
		default:
			break;
	}
	
	return (result);
}

/**
*@name: Set_IOUT_Switch
*@description: switching control
*@params: channel: channel number
		  value: 1: ON,0:OFF
*@return: IO status
*/
uint8_t Set_IOUT_Switch(uint8_t channel, uint8_t value)
{
	uint8_t result=0;
	uint8_t cnt=3;
	
	switch(channel)
	{
		case 0:
			if(value)
			{
				if((AlarmStatus.alarm.SHORT1==0) 
					&& (AlarmStatus.alarm.VIN_STATUS_ERR==0)
					&& (AlarmStatus.alarm.OTP==0))
				{
					PS1_ON();
				}
				EnableOpen.open.PS1_OPEN=1;
			}
			else
			{				
				PS1_OFF();
				EnableOpen.open.PS1_OPEN=0;
			}
			while(cnt--);
			result=PS1_STATUS();
			break;
		case 1:
			if(value)
			{				
				if((AlarmStatus.alarm.SHORT2==0) 
					&& (AlarmStatus.alarm.VIN_STATUS_ERR==0)
					&& (AlarmStatus.alarm.OTP==0))
				{
					PS2_ON();
				}
				EnableOpen.open.PS2_OPEN=1;
			}
			else
			{
				PS2_OFF();
				EnableOpen.open.PS2_OPEN=0;
			}
			while(cnt--);
			result=PS2_STATUS();
			break;
		case 2:
			if(value)
			{				
				if((AlarmStatus.alarm.SHORT3==0) 
					&& (AlarmStatus.alarm.VIN_STATUS_ERR==0)
					&& (AlarmStatus.alarm.OTP==0))
				{
					PS3_ON();
				}
				EnableOpen.open.PS3_OPEN=1;
			}
			else
			{
				PS3_OFF();
				EnableOpen.open.PS3_OPEN=0;
			}
			while(cnt--);
			result=PS3_STATUS();
			break;
		case 3:
			if(value)
			{				
				if((AlarmStatus.alarm.SHORT4==0) 
					&& (AlarmStatus.alarm.VIN_STATUS_ERR==0)
					&& (AlarmStatus.alarm.OTP==0))
				{
					PS4_ON();
				}
				EnableOpen.open.PS4_OPEN=1;
			}
			else
			{
				PS4_OFF();
				EnableOpen.open.PS4_OPEN=0;
			}
			while(cnt--);
			result=PS4_STATUS();
			break;
		case 4:
			if(value)	
			{				
				if((AlarmStatus.alarm.SHORT5==0) 
					&& (AlarmStatus.alarm.VIN_STATUS_ERR==0)
					&& (AlarmStatus.alarm.OTP==0))
				{
					PS5_ON();
				}
				EnableOpen.open.PS5_OPEN=1;
			}
			else
			{
				PS5_OFF();
				EnableOpen.open.PS5_OPEN=0;
			}
			while(cnt--);
			result=PS5_STATUS();
			break;
		case 5:
			if(value)
			{				
				if((AlarmStatus.alarm.SHORT6==0) 
					&& (AlarmStatus.alarm.VIN_STATUS_ERR==0)
					&& (AlarmStatus.alarm.OTP==0))
				{
					PS6_ON();
				}
				EnableOpen.open.PS6_OPEN=1;
			}
			else
			{
				PS6_OFF();
				EnableOpen.open.PS6_OPEN=0;
			}
			while(cnt--);
			result=PS6_STATUS();
			break;
		case 6:
			if(value)
			{				
				if((AlarmStatus.alarm.SHORT7==0) 
					&& (AlarmStatus.alarm.VIN_STATUS_ERR==0)
					&& (AlarmStatus.alarm.OTP==0))
				{
					PS7_ON();
				}
				EnableOpen.open.PS7_OPEN=1;
			}
			else
			{
				PS7_OFF();
				EnableOpen.open.PS7_OPEN=0;
			}
			while(cnt--);
			result=PS7_STATUS();
			break;
		case 7:
			if(value)
			{				
				if((AlarmStatus.alarm.SHORT8==0) 
					&& (AlarmStatus.alarm.VIN_STATUS_ERR==0)
					&& (AlarmStatus.alarm.OTP==0))
				{
					PS8_ON();
				}
				EnableOpen.open.PS8_OPEN=1;
			}
			else
			{
				PS8_OFF();
				EnableOpen.open.PS8_OPEN=0;
			}
			while(cnt--);
			result=PS8_STATUS();
			break;
		default:
			break;
	}//end switch
	
	if(result)
	{
		result=0;
	}
	else
	{
		result=1;
	}
	
	return (result);
}

///**
//*@name: Get_IOUT_Switch
//*@description: get the switching status
//*@params: channel: channel number		  
//*@return: 1:ON, 0:OFF
//*/
//uint8_t Get_IOUT_Switch(uint8_t channel)
//{
//	uint8_t result=0;
//	
//	switch(channel)
//	{
//		case 0:			
//			//result=PS1_STATUS();
//			result=AlarmStatus.alarm.PSON_1;
//			break;
//		
//		case 1:			
//			//result=PS2_STATUS();
//			result=AlarmStatus.alarm.PSON_2;
//			break;
//		
//		case 2:			
//			//result=PS3_STATUS();
//			result=AlarmStatus.alarm.PSON_3;
//			break;
//		
//		case 3:			
//			//result=PS4_STATUS();
//			result=AlarmStatus.alarm.PSON_4;
//			break;
//		
//		case 4:			
//			//result=PS5_STATUS();
//			result=AlarmStatus.alarm.PSON_5;
//			break;
//		
//		case 5:			
//			//result=PS6_STATUS();
//			result=AlarmStatus.alarm.PSON_6;
//			break;
//		
//		case 6:			
//			//result=PS7_STATUS();
//			result=AlarmStatus.alarm.PSON_7;
//			break;
//		
//		case 7:			
//			//result=PS8_STATUS();
//			result=AlarmStatus.alarm.PSON_8;
//			break;
//		
//		default:
//			break;
//	}
//	
//	return (result);
//}


/**
*@name: UART1_Comm_Data_Complete
*@description: send out response to the upper machine if the frame received is valid
*@params: command: command
*@return: none
*/
static void UART1_Comm_Data_Complete(uint8_t command)
{
	uint8_t	cTemp = 10;
	uint8_t i=0;
	uint8_t *pos=__NULL;
	uint8_t tlv_len=0;//TLV=1+2+(1 or 2)
	uint8_t data_len=data_len;
	uint16_t id=0;
	uint16_t iout=0;
	uint16_t crc16=0;
	
	UART1_STRUCT.T_OutPtr = 0;
	UART1_STRUCT.T_Transferred_OutPtr = 0;
	
	//UART1_STRUCT.T_Buffer[UART1_STRUCT.T_OutPtr++] = SOI;
	for(i=0;i0)
	{
		while(object_num--)
		{
			tlv_len=*pos;
			data_len=tlv_len-2-1;//object data length, please refer to the TLV
			/*if(data_len>2){break;}*/
			id=*(pos+2)<<8|*(pos+1);//object id
			switch(id)
			{
				case TLV_CHL_OCP+0://OCP
				case TLV_CHL_OCP+1:
				case TLV_CHL_OCP+2:
				case TLV_CHL_OCP+3:
				case TLV_CHL_OCP+4:
				case TLV_CHL_OCP+5:
				case TLV_CHL_OCP+6:
				case TLV_CHL_OCP+7:
					id-=TLV_CHL_OCP;
					*(pos+3)=Get_OCP_Status(id);
					break;
				
				case TLV_CHL_OUTPUT_ERR+0://Output Error
				case TLV_CHL_OUTPUT_ERR+1:
				case TLV_CHL_OUTPUT_ERR+2:
				case TLV_CHL_OUTPUT_ERR+3:
				case TLV_CHL_OUTPUT_ERR+4:
				case TLV_CHL_OUTPUT_ERR+5:
				case TLV_CHL_OUTPUT_ERR+6:
				case TLV_CHL_OUTPUT_ERR+7:
					id-=TLV_CHL_OUTPUT_ERR;
					*(pos+3)=Get_VOUT_Status(id);
					break;
				
				case TLV_CHL_CURRENT+0://Current
				case TLV_CHL_CURRENT+1:
				case TLV_CHL_CURRENT+2:
				case TLV_CHL_CURRENT+3:
				case TLV_CHL_CURRENT+4:
				case TLV_CHL_CURRENT+5:
				case TLV_CHL_CURRENT+6:
				case TLV_CHL_CURRENT+7:
					id-=TLV_CHL_CURRENT;
					iout=Get_IOUT_Value(id);
					*(pos+3)=iout%256;
					*(pos+4)=iout>>8;
					break;
				
				case TLV_CHL_ON_OFF+0://ON/OFF Control
				case TLV_CHL_ON_OFF+1:
				case TLV_CHL_ON_OFF+2:
				case TLV_CHL_ON_OFF+3:
				case TLV_CHL_ON_OFF+4:
				case TLV_CHL_ON_OFF+5:
				case TLV_CHL_ON_OFF+6:
				case TLV_CHL_ON_OFF+7:
					id-=TLV_CHL_ON_OFF;
					*(pos+3)=Set_IOUT_Switch(id, *(pos+3));
					break;
				
				case 0x0C00://Input voltage
					id-=0x0C00;					
					*(pos+3)=VOS_OUT%256;
					*(pos+4)=VOS_OUT>>8;
					break;
				/*
				case 0x0D00://Pin status
					id-=0x0D00;
					*(pos+3)=Get_IOUT_Switch(id);
					break;
				*/
				case TLV_MODULE_TYPE://Module type
					for(i=0;i2)
			//{
				//break;
			//}
			id=*(pos+2)<<8|*(pos+1);//object id
			if(id>=TLV_CHL_OCP && id<=TLV_CHL_OCP+7)//OCP warning
			{
				id-=TLV_CHL_OCP;
				*(pos+3)=Get_OCP_Status(id);
			}
			else if(id>=TLV_CHL_OUTPUT_ERR && id<=TLV_CHL_OUTPUT_ERR+7)//output warning
			{
				id-=TLV_CHL_OUTPUT_ERR;
				*(pos+3)=Get_VOUT_Status(id);
			}
			else if(id>=TLV_CHL_CURRENT && id<=TLV_CHL_CURRENT+7)//current
			{
				id-=TLV_CHL_CURRENT;
				iout=Get_IOUT_Value(id);
				*(pos+3)=iout%256;
				*(pos+4)=iout>>8;
			}			
			else if(id>=TLV_CHL_ON_OFF && id<=TLV_CHL_ON_OFF+7)//switching control
			{
				id-=TLV_CHL_ON_OFF;
				*(pos+3)=Set_IOUT_Switch(id, *(pos+3));				
			}
			else if(id>=0x0C00&&id<=0x0C07)//input voltage, test purpose
			{
				id-=0x0C00;
				//iout=Get_IOUT_Value(id);
				*(pos+3)=VOS_OUT%256;
				*(pos+4)=VOS_OUT>>8;
			}
			else if(id>=0x0D00&&id<=0x0D07)//switching status
			{
				id-=0x0D00;
				*(pos+3)=Get_IOUT_Switch(id);
			}
			else
			{
				if(id==TLV_MODULE_TYPE)
				{
					for(i=0;i>8;	
	
	i = 0;
	UART1_STRUCT.T_Buffer[UART1_STRUCT.T_OutPtr++]=UART1_STRUCT.T_Transferred[i];
	for(i=1;i>8;
	
	i = 0;
	UART1_STRUCT.T_Buffer[UART1_STRUCT.T_OutPtr++]=UART1_STRUCT.T_Transferred[i];
	for(i=1;i= RECEIVE_DATA_LEN)//maximum data length
	{
  		UART1_STRUCT.R_InPtr = 0;
	}
	
	/*
	if(UART1_STRUCT.R_InPtr >= (RECEIVE_DATA_LEN-1))
	{
  		UART1_STRUCT.R_InPtr = 0;
	}*/
  	
  	UART1_STRUCT.R_Buffer[UART1_STRUCT.R_InPtr++] = USART_ReceiveData(USARTy);//save the byte
	rcv_timeout=0;//once we received a byte, clear the timer to prepare for the next byte
  	
   	if(UART1_STRUCT.R_Buffer[0] != SOI)
  	{
  		UART1_STRUCT.R_InPtr = 0;
  		return;
  	}
  	else if(UART1_STRUCT.R_InPtr <= 1)
  	{
  		return;
  	}
  	
    //receive a frame
  	if((UART1_STRUCT.R_InPtr >= MINUMUM_DATA_LEN) && (UART1_STRUCT.R_Buffer[UART1_STRUCT.R_InPtr - 1] == EOI))						
	{			
		UART1_STRUCT.R_Flag = 1;
	}
}


/**
*@name: UART1_Data_Send
*@description: transmit interrupt service routine
*@params: none
*@return: none
*/
void USART1_Data_Send(void)
{
	if(UART1_STRUCT.T_Length != 0)
	{
		//RS485_Delay = 3;
		UART1_STRUCT.T_Length--;
		USART_SendData(USARTy, UART1_STRUCT.T_Buffer[UART1_STRUCT.T_OutPtr++]);
		while (USART_GetFlagStatus(USARTy, USART_FLAG_TXDE) == RESET);
	}
	else//last byte
	{
		UART1_STRUCT.T_DTSime = 0;
        
        //wait for the bit-shift register to be empty
        while(USART_GetFlagStatus(USARTy, USART_FLAG_TXDE)==RESET)
            ;
		//wait for the last byte to be transmitted
		while(USART_GetFlagStatus(USARTy, USART_FLAG_TXC)==RESET)
            ;
        //RS485_L();//receive mode
		USART_ConfigInt(USARTy, USART_INT_TXDE, DISABLE);//disable the transmit interrupt
	}	
}

6、usart.h

#ifndef __USART_H__
#define __USART_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "n32g031.h"

#define _USART1_

#ifdef _USART1_
#define USARTy            	USART1
#define USARTy_CLK        	RCC_APB2_PERIPH_USART1
#define USARTy_GPIO       	GPIOA
#define USARTy_GPIO_CLK   	RCC_APB2_PERIPH_GPIOA
#define USARTy_RxPin      	GPIO_PIN_10
#define USARTy_TxPin      	GPIO_PIN_9
#define USARTy_Rx_GPIO_AF 	GPIO_AF4_USART1
#define USARTy_Tx_GPIO_AF 	GPIO_AF4_USART1
#define USARTy_APBxClkCmd 	RCC_EnableAPB2PeriphClk
#define USARTy_IRQn       	USART1_IRQn//USART1_2_IRQn
#define USARTy_IRQHandler 	USART1_IRQHandler//USART1_2_IRQHandler
#endif

#define RECEIVE_DATA_LEN	128		//maximum data length received
#define TRANSMIT_DATA_LEN	128		//maximum data length to be sent
#define	MINUMUM_DATA_LEN	15		//minumum data length of valid data
#define	DATA_EXCLUDED_LEN	11		//length except all the flags including start and end bytes, command and protocols, etc.

#define	USART_BAUD_RATE		9600	//baud rate of UART
#define ID_Address			0x01	//ID
#define	NO_BASE_ID			0xB0	//does not match the ID
#define	CRC_ERROR			0x05	//CRC error

/*
======================================================

			***一个最小数据包的长度组成***
------------------------------------------------------
			1、起始标志:		0x7E	1字节
			2、版本:			0x01	1字节
			3、承载协议类型:	0x03	1字节
			4、模块编号			0x01	1字节
			5、模块类型			0x06	1字节
			6、控制协议标识		0x01	1字节
			7、命令标识					1字节
			8、应答标志			0xFF	1字节
			9、对象长度					1字节
			10、对象标识				2字节
			11、对象内容				最小1字节
			12、CRC校验					2字节
			13、结束标志				1字节			

======================================================
*/


/*
======================================================

			Start and End Flas and Other Macros

======================================================
*/
#define		SOI					0x7E    //start
#define		CID1				0x42    //not used here
#define		EOI					0x7E    //end
#define		VERSION				0x01	//version of the identification protocol, fixed value: 0x01
#define		PROTOCOL			0x03	//标识所承载的协议类型,fixed value: 0x03
#define		PSE
#ifdef		PSE
#define		MODULE_TYPE			0x80	//module type definition, default value: 0x06, PSE: 0x80:
#else
#define		MODULE_TYPE			0x06
#endif
#define		CTL_PROTOCOL_ID		0x01	//upper protocol type, fixed value: 0x01
/*
======================================================

			Command Type

======================================================
*/
#define		CMD_QUERY			0xB1	//Query command
#define		CMD_CONFIGURE		0xB2	//Configure command
#define		CMD_SYS_RESET		0xC0	//System reset command

/*
======================================================

			Acknowledgement Code

======================================================
*/
#define		NORMAL				0x00	//command is executed successfully
#define		CONFINED_EXECUTED	0x01	//the command is executed conditionally
#define		CMD_ERROR			0x02	//invalid command
#define		DATA_ERROR			0x03	//data length error or data error
#define		RESERVED			0x04	//reserved


/*
======================================================

			TLV Object Definition

======================================================
*/
#define 	TLV_MODULE_TYPE		0x0800	//module type, maximum 20 bytes
#define		TLV_SW_VERSION		0x0801	//software version, maximum 20 bytes
#define		TLV_CHL_CURRENT		0x0900	//query current base address
#define		TLV_CHL_OCP			0x0A00	//OCP warning base address
#define		TLV_CHL_OUTPUT_ERR	0x0A10	//output error base address
#define		TLV_OTP				0x0A20	//OTP
#define		TLV_CHL_ON_OFF		0x0B00	//switch control

//UART interface
struct		UART_Data_Struct
{
	uint8_t	R_Buffer[RECEIVE_DATA_LEN];	//receive buffer, the original data frame from USRT interface which maybe contains transferred bytes, such as 0x5E,0x5D and 0x5E,0x7D
	uint8_t R_Detransferred[RECEIVE_DATA_LEN];//data buffer containing the acutal data frame, that is, not transferred
	uint8_t R_Detransferred_Ptr;		//receive data length which is detransferred
	uint8_t	R_Length;					//total length of the original data frame
	uint8_t	R_InPtr;					//length of the received data
	uint8_t	R_Flag;						//get the complete data frame?
	uint8_t	R_DTSime;					//receive timeout setting
	
	uint8_t	T_Buffer[TRANSMIT_DATA_LEN];//transmit data buffer, the actual data to be sent out to the upper machine
	uint8_t	T_Transferred[TRANSMIT_DATA_LEN];//a temporary buffer to store the untransferred data
	uint8_t	T_Transferred_OutPtr;		//used with the member T_Transferred
	uint8_t	T_Length;					//total length of data frame to be transmitted
	uint8_t	T_OutPtr;					//length of data frame transmitted
	uint8_t	T_Flag;						//the last byte of the whole frame is transmitted?
	uint8_t	T_DTSime;					//transmit timeout setting
	
	uint8_t	T_Time;
	uint8_t	Frame_Buffer[RECEIVE_DATA_LEN];//the following members are not used yet
	uint8_t	Frame_InPtr;    
	uint8_t	Frame_OutPtr;
	uint8_t	Frame_Length; 
};

/*
#define USARTz            	USART2
#define USARTz_GPIO       	GPIOA
#define USARTz_CLK        	RCC_APB1_PERIPH_USART2
#define USARTz_GPIO_CLK   	RCC_APB2_PERIPH_GPIOA
#define USARTz_RxPin      	GPIO_PIN_3
#define USARTz_TxPin      	GPIO_PIN_2
#define USARTz_Rx_GPIO_AF 	GPIO_AF4_USART2
#define USARTz_Tx_GPIO_AF 	GPIO_AF4_USART2
#define USARTz_APBxClkCmd 	RCC_EnableAPB1PeriphClk
#define USARTz_IRQn       	USART2_IRQn
#define USARTz_IRQHandler 	USART2_IRQHandler
#endif
*/

//typedef enum
//{
    //FAILED = 0,
    //PASSED = !FAILED
//} TestStatus;


//void RCC_Configuration(void);
//TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength);
void USART_Configuration(void);
static void USART_NVIC_Configuration(void);
void RS485_Configuration(void);
void USART1_Data_Receive(void);
void USART1_Data_Send(void);
void USART1_Process(void);
uint8_t Get_OCP_Status(uint8_t channel);
uint8_t Get_VOUT_Status(uint8_t channel);
uint16_t Get_IOUT_Value(uint8_t channel);
uint8_t Set_IOUT_Switch(uint8_t channel, uint8_t value);
uint8_t Get_IOUT_Switch(uint8_t channel);

#ifdef __cplusplus
}
#endif

#endif /* __USART_H__ */

7、timer.c

#include "n32g031.h"
#include "timer.h"

uint16_t PrescalerValue = 0;	//prescaler coeffiecient of timer1


/**
*@name: TIM3_NVIC_Configuratio
*@description: timer3 interrupt priority configuration
*@params: none
*@return: none
*/
static void TIM3_NVIC_Configuration(void)
{
    NVIC_InitType NVIC_InitStructure;

    /* Enable the TIM3 global Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel                   = TIM3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority           = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;

    NVIC_Init(&NVIC_InitStructure);
}

/**
*@name: TIM3_Configuration
*@description: timer3 configuration
*@params: none
*@return: none
*/
void TIM3_Configuration(void)
{
	TIM_TimeBaseInitType TIM_TimeBaseStructure;
	
	TIM3_NVIC_Configuration();
	
    // Compute the prescaler value
    PrescalerValue = 0; //(uint16_t) (SystemCoreClock / 12000000) - 1;

    // Time base configuration
    TIM_TimeBaseStructure.Period    = TIMER_1MS;
    TIM_TimeBaseStructure.Prescaler = 0;
    TIM_TimeBaseStructure.ClkDiv    = 0;
    TIM_TimeBaseStructure.CntMode   = TIM_CNT_MODE_UP;

    TIM_InitTimeBase(TIM3, &TIM_TimeBaseStructure);

    // Prescaler configuration
    TIM_ConfigPrescaler(TIM3, PrescalerValue, TIM_PSC_RELOAD_MODE_IMMEDIATE);

    // TIM3 enable update irq
    TIM_ConfigInt(TIM3, TIM_INT_UPDATE, ENABLE);

    // TIM3 enable counter
    TIM_Enable(TIM3, ENABLE);	
}

/**
*@name: TIM6_NVIC_Configuration
*@description: timer6 interrupt configuration
*@params: none
*@return: none
*/
static void TIM6_NVIC_Configuration(void)
{
    NVIC_InitType NVIC_InitStructure;

    /* Enable the TIM6 global Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel                   = LPTIM_TIM6_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority           = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;

    NVIC_Init(&NVIC_InitStructure);
}

/**
*@name: TIM6_Configuration
*@description: timer6 configuration
*@params: none
*@return: none
*/
void TIM6_Configuration(void)
{
	TIM_TimeBaseInitType TIM_TimeBaseStructure;
	
	TIM6_NVIC_Configuration();
	
    // Compute the prescaler value
    PrescalerValue = 0; //(uint16_t) (SystemCoreClock / 12000000) - 1;

    // Time base configuration
    TIM_TimeBaseStructure.Period    = TIMER_1MS;
    TIM_TimeBaseStructure.Prescaler = 0;
    TIM_TimeBaseStructure.ClkDiv    = 0;
    TIM_TimeBaseStructure.CntMode   = TIM_CNT_MODE_UP;

    TIM_InitTimeBase(TIM6, &TIM_TimeBaseStructure);

    // Prescaler configuration
    TIM_ConfigPrescaler(TIM6, PrescalerValue, TIM_PSC_RELOAD_MODE_IMMEDIATE);

    // TIM6 enable update irq
    TIM_ConfigInt(TIM6, TIM_INT_UPDATE, ENABLE);

    // TIM6 enable counter
    TIM_Enable(TIM6, ENABLE);	
}

8、timer.h

#ifndef __TIMER_H__
#define __TIMER_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "n32g031.h"

//APB1时钟来源于48M系统时钟4分频
//TIM3使用APB1时钟,看手册TIM3的时钟配置,如果APB1是1分频,则timer3的时钟频率=APB1*1,否则=APB1*2
//由于APB1是4分频,因此TIM3的时钟是:APB1*2=(48M/4)*2=24M,定义1毫秒计数:x/24000000=0.001(s),求得x=24000
#define 	TIMER_1MS	24000	//system clocks needed for 1 milli-second timeout

void TIM3_Configuration(void);
void TIM6_Configuration(void);

#ifdef __cplusplus
}
#endif

#endif /* __TIMER_H__ */

9、crc16.c

#include "n32g031.h"
#include "main.h"

/**
 * @param data byte array
 * @return  the decimal value of CRC16
 */
 /*
public static int getCrc16(byte[] data){
	System.out.println("\nCRC 16 calculation progress:\n");
	int current_crc_value = PRESET_VALUE;
	for (int i = 0; i < data.length; i++){
		current_crc_value ^= data[i] & 0xFF;
		for (int j = 0; j < 8; j++ ) {
			if ((current_crc_value & 1) != 0) {
				current_crc_value = (current_crc_value >>> 1) ^ POLYNOMIAL;
			}
			else{
				current_crc_value = current_crc_value >>> 1;
			}
		}
	}
	return current_crc_value & 0xFFFF;
}
*/

#define	 PRESET_VALUE  	0xFFFF
#define	 POLYNOMIAL 	0xA001


//private static final int POLYNOMIAL = /*0xA053;*//*0x0589*/0xA001;
/*    02 05 00 03 FF 00 的不同crc计算值:
CRC-16 0x127C
CRC-16 (Modbus)    0x097C 对应的多项式为 0xA001
CRC-16 (Sick)  0xE2F0
CRC-CCITT (XModem) 0xF2B8
CRC-CCITT (0xFFFF) 0xFCA8
CRC-CCITT (0x1D0F) 0xC386
CRC-CCITT (Kermit) 0xA63E
CRC-DNP    0x6E28*/


/*==================================================================================

		******校验码的计算多项式(X16 + X15 + X2 + 1)算法原理******

        1.预置1个16位的寄存器为十六进制FFFF(即全为1);称此寄存器为CRC寄存器;
        2.把第一个8位二进制数据 (既通讯信息帧的第一个字节)与16位的CRC寄存器的低8位相异或,把结果放于CRC寄存器;
        3.把CRC寄存器的内容右移一 位(朝低位)用0填补最高位,并检查右移后的移出位;
        4.如果移出位为0:重复第3步(再次右移一位);
		   如果移出位为1:CRC寄存器与多项式A001(1010 0000 0000 0001)进行异或;(Modbus)
        5.重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理;
        6.重复步骤2到步骤5,进行通讯信息帧下一个字节的处理;
        7.将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的高、低字节进行交换;
        8.最后得到的CRC寄存器内容即为:CRC码。

		
===================================================================================*/


/**
 * @name  getCRC16
 * @descrption: 将数组对象转换为对应的CRC16(CCITT 0xA001标准)
 * @param data byte数组
 * @return  CRC16校验得到的十进制int
 */
uint16_t getCRC16(uint8_t *data, uint8_t size)
{
	int current_crc_value = PRESET_VALUE;
	uint8_t i=0;
	while(size--)
	{		
		current_crc_value ^= (*data++ & 0xFF);
		for (i = 0; i < 8; i++ ) 
		{
			if ((current_crc_value & 1) != 0) {
				current_crc_value = (current_crc_value >> 1) ^ POLYNOMIAL;
			}
			else{
				current_crc_value = current_crc_value >> 1;
			}
		}
	}
	
	return current_crc_value & 0xFFFF;//the low 16-bit we want
}

/****************************Info********************************************** 
 * Name:    InvertUint8 
 * Note: 	把字节颠倒过来,如0x12变成0x48
			0x12: 0001 0010
			0x48: 0100 1000
 *****************************************************************************/
/*
static void InvertUint8(uint8_t *dBuf,uint8_t *srcBuf)
{
	int i;
	uint8_t tmp[4]={0};
 
	for(i=0;i< 8;i++)
	{
		if(srcBuf[0]& (1 << i))
		tmp[0]|=1<<(7-i);
	}
	dBuf[0] = tmp[0];	
}

static void InvertUint16(unsigned short *dBuf,unsigned short *srcBuf)
{
	int i;
	unsigned short tmp[4]={0};
 
	for(i=0;i< 16;i++)
	{
		if(srcBuf[0]& (1 << i))
		tmp[0]|=1<<(15 - i);
	}
	dBuf[0] = tmp[0];
}
*/

/*==================================================================================

		******CRC16 CCITT x16+x12+x5+1(0x11021)的算法原理******

		1.根据CRC16的标准选择初值CRCIn的值。

		2.将数据的第一个字节与CRCIn高8位异或。

		3.判断最高位,若该位为 0 左移一位,若为 1 左移一位再与多项式Hex码异或。

		4.重复3直至8位全部移位计算结束。

		5.重复将所有输入数据操作完成以上步骤,所得16位数即16位CRC校验码。
		
===================================================================================*/

/************************************************************************************************
 @* Name:    CRC-16/CCITT        x16+x12+x5+1 
 @* Width:	16
 @* Poly:    0x11021 
 @* Init:    0xFFFF 
 @* Refin:   false,输入不用反转 
 @* Refout:  false, 输出不用反转 
 @* Xorout:  0x0000 
 @* Alias:   CRC-CCITT,CRC-16/CCITT-TRUE,CRC-16/KERMIT
 @* CRC16_CCITT:多项式x16+x12+x5+1(0x1021),初始值0xFFFF,高位在前,低位在后,结果与0xFFFF异或
 ***********************************************************************************************/
uint16_t CRC16_CCITT(uint8_t *data, uint8_t datalen)
{
	//unsigned short wCRCin = 0xFFFF;
	unsigned short wCRCin = 0x0000;//0xFFFF;使用XMODEM的CRC16算法,区别是初值不同
	unsigned short wCPoly = 0x1021;//本来是0x11021,但只取16位,最高位1去掉
	uint8_t wChar = 0;
	uint8_t i=0;
	
	while (datalen--) 	
	{
		wChar = *(data++);
		//InvertUint8(&wChar,&wChar);//反转时用
		wCRCin ^= (wChar << 8);
		for(i = 0;i < 8;i++)
		{
			if(wCRCin & 0x8000)//如果最高位是1则左移1位并与多项式wCPoly相异或
				wCRCin = (wCRCin << 1) ^ wCPoly;
			else
				wCRCin = wCRCin << 1;//否则直接左移1位
		}
	}
	//InvertUint16(&wCRCin,&wCRCin);//反转时用
	return (wCRCin);
}

/**
*@name: CRC16
*@description: CRC计算,经测试:这种方法也是可以正常使用的			   
*@params: buffer: 要计算的数组
          size: 数据长度
*@return: 返回相应的16位结果
*/
uint16_t CRC16(const uint8_t *buffer, uint8_t size)
{
	uint16_t crc=0xFFFF;//initial value, can also be 0x0000
    if(__NULL!=buffer && size>0)
    {
        while(size--)
        {
            crc=(crc>>8)|(crc<<8);//高低字节交换
            crc^=*buffer++;
            crc^=((uint8_t)crc)>>4;
            crc^=crc<<12;
            crc^=(crc&0xFF)<<5;
        }
    }
    
    return crc;
}

10、crc16.h

#ifndef __CRC16_H__
#define __CRC16_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "n32g031.h"

uint16_t CRC16_CCITT(uint8_t *data, uint8_t datalen);
	
#ifdef __cplusplus
}
#endif

#endif /* __CRC16_H__ */

11、iwdg.c

#include "main.h"

__IO uint32_t LsiFreq     = 30000;//LSI clock frequency


/**
*@name: IWDG_Init
*@description: Initialize the watchdog, using the 128 prescaler of LSI.
			   The timeout period is about one second.
*@params: None
*@return: None
*/
void IWDG_Init(void)
{
	RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_PWR, ENABLE);
    DBG_ConfigPeriph(DBG_IWDG_STOP, ENABLE);//stop IWDG while debugging
	
	//Check if the system has resumed from IWDG reset
    if (RCC_GetFlagStatus(RCC_CTRLSTS_FLAG_IWDGRSTF) != RESET)
    {
        /* IWDGRST flag set */
        /* Clear reset flags */
        RCC_ClrFlag();
    }
	
	/* IWDG timeout equal to 250 ms (the timeout may varies due to LSI frequency
       dispersion) */
    //Enable write access to IWDG_PR and IWDG_RLR registers
    IWDG_WriteConfig(IWDG_WRITE_ENABLE);

    //IWDG counter clock: LSI/128
    IWDG_SetPrescalerDiv(IWDG_PRESCALER_DIV128);

    /* Set counter reload value to obtain 1000ms IWDG TimeOut.
       Counter Reload Value = 1000ms/IWDG counter clock period
                            = 1000ms / (LSI/128)
                            = 4.27ms / (LsiFreq/128)
     */
    //log_debug("LsiFreq is: %d\n", LsiFreq);
    IWDG_CntReload(234);//234*4.27~=1000(ms)
    
	//Reload IWDG counter
    IWDG_ReloadKey();//each time we write 0xAAAA to register IWDG_KEY, the reload value will be transferred to the counter.

    //Enable IWDG (the LSI oscillator will be enabled by hardware)
    IWDG_Enable();//write 0xCCCC to register IWDG_KEY to start the watchdog
}

12、iwdg.h

#ifndef __IWDG_H__
#define __IWDG_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "n32g031.h"

void IWDG_Init(void);
	
#ifdef __cplusplus
}
#endif

#endif /* __IWDG_H__ */

13、i2c_slave.c


#include "n32g031_i2c.h"
#include "n32g031.h"
#include "i2c_slave.h"
#include "main.h"
#include "crc16.h"
#include 

#define     NO_ERROR        0
#define     UNKNOWN_ERROR   1
#define     UNKNOWN_ID      2
#define     M_TYPE          0x01B0
#define     SW_VERSION      0x01B1
#define     R_CURRENT       0x05C0 //0x05C0~0x05C7
#define     R_OCP           0x03B1 //0x03B1~0x03B8
#define     R_OUT_ERROR     0x03B9 //0x03B9~0x03C0
#define     R_OTP           0x03C1
#define     W_SWITCH        0x0620 //0x0620~0x0627
#define		R_TEMP			0x0501 //temperature data
#define     R_PIN_STATUS    0x0D00 //0x0D00~0x0D07, for test purpose

const char m_type[] = "PSE-D48P8S75A"; //module name
const char sw_version[] = "V1.0"; //software version

uint8_t data_rx_buf[BUFFER_SIZE] = {0};//data buffer
uint8_t data_tx_buf[BUFFER_SIZE] = {0};//data buffer for I2C2
static __IO uint32_t I2CTimeout;
//volatile uint8_t flag_slave_recv_finish = 0;//received flag
volatile uint8_t flag_slave_send_finish = 0;//transmitted flag
//volatile uint8_t req_is_processed=0;//the request from the master has been processed
//static uint8_t rxDataNum = 0; //data length received
//static uint8_t txDataNum = 0; //data length transmitted

//static uint8_t RCC_RESET_Flag = 0;
//static uint8_t fb_status = 0x00;//status

volatile uint8_t iic_send_buffer[BUFFER_SIZE];

void CommTimeOut_CallBack(ErrCode_t errcode);

volatile _iicMaster iicMaster;  // useIT for master
volatile _iicSlave iicSlave;    // useIT for I2C1
volatile _iicSlave iicSlave2;   // useIT for I2C2

/**
 * =======================================================================================
 * =======================================================================================
 */

void I2C1_ResetBusy()
{
    I2C1->CTRL1 |= 0x8000;  // Reset Busy
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    I2C1->CTRL1 &= ~0x8000;
}

void I2C1_Config(void)
{
    I2C_InitType I2C_InitStructure;
    //I2C_InitType i2c1_slave;
    GPIO_InitType i2c1_gpio;
    //RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_I2C1, ENABLE);
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);

    GPIO_InitStruct(&i2c1_gpio);
    //PB6 -- SCL; PB7 -- SDA
    i2c1_gpio.Pin        = I2Cx_SCL_PIN | I2Cx_SDA_PIN;
    i2c1_gpio.GPIO_Speed = GPIO_SPEED_HIGH;
    i2c1_gpio.GPIO_Mode  = GPIO_MODE_AF_OD;//alternate open-drain
    i2c1_gpio.GPIO_Alternate = GPIO_AF_I2C;
    GPIO_InitPeripheral(GPIOx, &i2c1_gpio);

    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_I2C1, ENABLE);
    I2C_InitStructure.OwnAddr1 = I2C_SLAVE_ADDR;
    I2C_DeInit(I2C1);
    I2C1_ResetBusy();
    I2C_InitStructure.BusMode     = I2C_BUSMODE_I2C;
    I2C_InitStructure.FmDutyCycle = I2C_FMDUTYCYCLE_2;
    I2C_InitStructure.AckEnable   = I2C_ACKEN;
    I2C_InitStructure.AddrMode    = I2C_ADDR_MODE_7BIT;
    I2C_InitStructure.ClkSpeed    = 100000;  // 100K
    I2C_Init(I2C1, &I2C_InitStructure);      // Initial and Enable I2Cx
    I2C_Enable(I2C1, ENABLE);
}

void I2C1_NVIC_Config(void)
{
    NVIC_InitType NVIC_InitStructure;

    NVIC_InitStructure.NVIC_IRQChannel    = I2C1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 0x01;
    NVIC_Init(&NVIC_InitStructure);
    NVIC_InitStructure.NVIC_IRQChannel++;  // I2Cx_ER_IRQn
    NVIC_Init(&NVIC_InitStructure);
    I2C_ConfigInt(I2C1, I2C_INT_EVENT | I2C_INT_BUF | I2C_INT_ERR, NVIC_InitStructure.NVIC_IRQChannelCmd);
}

void I2C1_ResetInit()
{
    I2C1_Config();
    I2C1_NVIC_Config();  // #define I2Cx_UseIT
}

/**
 * =======================================================================================
 * =======================================================================================
 */
void I2C1_Initial(void)
{
    I2C1_ResetInit();
}

/**
 * @brief  I2Cx interrupt callback function
 * @param I2Cx I2C1
 */
//void I2C_EV_IRQ_CallBack(volatile _iicMaster* iicMaster, volatile _iicSlave* iicSlave)
void I2C1_IRQHandler(void)
{
    uint32_t last_event = I2C_GetLastEvent(I2C1);
    if ((last_event & I2C_ROLE_MASTER) != I2C_ROLE_MASTER)
    {
        switch (last_event) {
            /* Slave Tx */
            case I2C_EVT_SLAVE_SEND_ADDR_MATCHED:  // 0x00060082.EV1.EV3_1 (ADDRF TXDATE)
            case I2C_EVT_SLAVE_DATA_SENDING:       // 0x00060080.EV3 (TXDATE)
            case I2C_EVT_SLAVE_DATA_SENDED:        // 0x00060084.EV3_2 (TXDATE BSF)
                /*
                if (iicSlave.ptr < IIC_Slave_BufSize) {
                    I2C_SendData(I2C1, iicSlave.buf[iicSlave.ptr++]);  // clear TXDATE
                } else {
                    I2C_SendData(I2C1, 0xFF);  // clear TXDATE
                }
                */
                switch (iicSlave.buf[0])
                {
                    case PSU_INFO:
                        if (iicSlave.ptr < IIC_Slave_BufSize) {
                            //I2C_SendData(I2C1, iicSlave.buf[iicSlave.ptr++]);  // clear TXDATE
                            I2C_SendData(I2C1, iic_send_buffer[iicSlave.ptr++]);  // clear TXDATE
                        } else {
                            I2C_SendData(I2C1, 0xFF);  // clear TXDATE
                        }
                        break;
                    default:
                        data_rx_buf[0] = 0x00;
                        I2C1->DAT = 0xFF;
                        break;
                }
                break;
            /* Slave Rx */
            case I2C_EVT_SLAVE_RECV_ADDR_MATCHED:  // 0x00020002.EV1 (ADDRF)
                iicSlave.ptr = 0;
                if (IIC_Slave_BufSize > 256) {
                    iicSlave.ptrSt = 1;  //
                } else {
                    iicSlave.ptrSt = 2;  //
                }
                //I2C_RecvData(I2C1);
                break;
            case I2C_EVT_SLAVE_DATA_RECVD:  // 0x00020040.EV2 (RXDATNE)
                switch (iicSlave.ptrSt) {
                    case 1:                                                  // 实际并未执行case 1
                        iicSlave.ptr   = (uint16_t)I2C_RecvData(I2C1) << 8;  // clear RXDATNE
                        iicSlave.ptrSt = 2;                                  //
                        break;
                    case 2:                                    // write higher byte of ptr
                    //iicSlave.ptr += I2C_RecvData(I2C1);  // clear RXDATNE  //commented by Power on March 3rd, 2023
                    //iicSlave.ptrSt = 3;                  // 准备写buf数据
                    //break;
                    case 3:
                        if (iicSlave.ptr < IIC_Slave_BufSize) {
                            iicSlave.buf[iicSlave.ptr++] = I2C_RecvData(I2C1);  // clear RXDATNE
                            iicSlave.bufSt                = 1;  //data is updating now...
                        } else {
                            I2C_RecvData(I2C1);  // clear RXDATNE
                        }
                        break;
                    default:
                        I2C_RecvData(I2C1);  // clear RXDATNE
                        break;
                }
                break;
            case I2C_EVT_SLAVE_STOP_RECVD:   // 0x00000010.EV4 (STOPF)
                iicSlave.ptr = 0;
                I2C_Enable(I2C1, ENABLE);    // clear STOPF
                if (iicSlave.bufSt == 1) {
                    iicSlave.bufSt = 2;     //data updating is complete
                }
                /*======here we don't have any operation from upper machine
                switch(iicSlave.buf[0])
                {
                    case OUTPUT_CONTROL:
                        Set_Output_Switch(iicSlave.buf[1]);
                        //iicSlave.buf[1]=0xFF;
                        break;
                    default:
                        //iicSlave.buf[0]=0x00;
                        break;
                }*/
                break;
            default:
                I2C1_ResetInit();
                break;
        }
    }
}

///**
// * @brief  i2c slave Interrupt service function
// */
//void I2C1_IRQHandler_Backup(void)
//{
//    uint8_t timeout_flag = 0;
//    uint32_t last_event = 0;
//
//    last_event = I2C_GetLastEvent(I2C1);
//  if ((last_event & I2C_ROLE_MASTER) != I2C_ROLE_MASTER) // MSMODE = 0:I2C slave mode
//    {
//        switch (last_event)
//        {
//          //EV1: 主机发送的地址与本从机地址匹配(从机准备接收数据,也就是主机要发送数据给从机)
//          case I2C_EVT_SLAVE_RECV_ADDR_MATCHED: //0x00020002.EV1 Rx addr matched
//              //clear flag,ready to receive data
//              rxDataNum = 0;
//              break;
//
//          //EV1: 主机发送的地址与本从机地址匹配(主机要从从机获取数据,从机开始发送第一个数据给主机)
//          case I2C_EVT_SLAVE_SEND_ADDR_MATCHED: //0x00060082.EV1 Tx addr matched
//              txDataNum = 0;
//              rxDataNum = 0;
//              switch(data_rx_buf[0])
//              {
//                  case OUTPUT_CONTROL:
//                      //I2C1->DAT = fb_status;
//                      I2C1->DAT = 0x00;
//                      break;
//                  case OUTPUT_VOLTAGE_HIGH: //test purpose
//                      I2C1->DAT = VOS_OUT>>8;
//                      break;
//                  case OUTPUT_VOLTAGE_LOW: //test purpose
//                      I2C1->DAT = (uint8_t)VOS_OUT;
//                      break;
//
//                  default:
//                      data_rx_buf[0]=0x00;
//                      I2C1->DAT=0xFF;
//                      break;
//              }
//              break;
//
//          //EV3: SlaveTransmitter,数据正在发送中,此事件和I2C_EVT_SLAVE_DATA_SENDED类似
//          case I2C_EVT_SLAVE_DATA_SENDING:  //0x00060080. EV3 Sending data
//              break;
//
//          //EV3: 从机发送一个数据成功,收到主机回应后接着发送下一个数据(只有返回电流值时才会发送多个字节)
//          case I2C_EVT_SLAVE_DATA_SENDED:
//              break;
//
//          //EV2: SlaveReceiver,从机接收到并保存从主机发送来的数据
//          case I2C_EVT_SLAVE_DATA_RECVD: //0x00020040.EV2 one byte recved
//              if(rxDataNum < BUFFER_SIZE)
//              {
//                  data_rx_buf[rxDataNum++] = I2C1->DAT;
//              }
//              break;
//
//          //EV4: When the application is expecting the end of the communication: master sends a stop condition and data transmission is stopped.
//          //表示应用程序希望结束通信,也就是说EV4表明主机发送了一个STOP停止信号,从机接收数据完成
//          case I2C_EVT_SLAVE_STOP_RECVD: // 0x00000010 EV4
//              I2C_Enable(I2C1, ENABLE);
//              if(rxDataNum != 0)
//              {
//                  flag_slave_recv_finish = 1; // The STOPF bit is not set after a NACK reception
//              }
//              switch(data_rx_buf[0])
//              {
//                  //case OUTPUT_CONTROL:
//                      //Set_Output_Switch(data_rx_buf[1]);
//                      //data_rx_buf[1]=0xFF;
//                      //break;
//                  default:
//                      data_rx_buf[0]=0x00;
//                      break;
//              }
//              break;
//
//          default:
//              I2C_Enable(I2C1, ENABLE);
//              timeout_flag = 1;
//              break;
//        }
//    }
//
//    if (timeout_flag)//出现超时错误则根据错误代码重启I2C模块
//    {
//        if ((I2CTimeout--) == 0)
//        {
//            CommTimeOut_CallBack(SLAVE_UNKNOW);
//        }
//    }
//    else
//    {
//        I2CTimeout = I2CT_LONG_TIMEOUT;
//    }
//
//  //EV3_2: When the master sends a NACK in order to tell slave that data transmission
//  //shall end (before sending the STOP condition). In this case slave has to stop sending
//  //data bytes and expect a Stop condition on the bus.
//  //主机在发送STOP之前发送了一个NACK给从机,表示数据传输结束(主机接收完从机发送的数据,从机停止发送数据并等待主机发送STOP)
//    if(last_event == I2C_EVT_SLAVE_ACK_MISS)
//    {
//        I2C_ClrFlag(I2C1, I2C_FLAG_ACKFAIL);
//        if(txDataNum != 0)  //从机已发送最后一个数据并从主机收到NACK
//        {
//            flag_slave_send_finish = 1;//发送完成标志
//        }
//        else //还没有发送完数据就收到主机的NACK,产生EV3_2事件,表示发送出错
//        {
//
//        }
//    }
//}

/**
 * =======================================================================================
 * =======================================================================================
 */

void I2C2_ResetBusy()
{
    I2C2->CTRL1 |= 0x8000;  // Reset Busy
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    I2C2->CTRL1 &= ~0x8000;
}

/**
*@name: I2C2_Config
*@description: for the main communication with the upper machine
*@input: none
*@output: none
**/
void I2C2_Config(void)
{
    I2C_InitType I2C_InitStructure;
    //I2C_InitType i2c1_slave;
    GPIO_InitType i2c2_gpio;
    //RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_I2C1, ENABLE);
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);

    GPIO_InitStruct(&i2c2_gpio);
    //PA9 -- SCL; PA10 -- SDA
    i2c2_gpio.Pin        = I2C2_SCL_PIN | I2C2_SDA_PIN;
    i2c2_gpio.GPIO_Speed = GPIO_SPEED_HIGH;
    i2c2_gpio.GPIO_Mode  = GPIO_MODE_AF_OD;//alternate open-drain
    i2c2_gpio.GPIO_Alternate = GPIO_AF_I2C2;
    GPIO_InitPeripheral(GPIOy, &i2c2_gpio);

    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_I2C2, ENABLE);
    I2C_InitStructure.OwnAddr1 = I2C2_SLAVE_ADDR;
    I2C_DeInit(I2C2);
    I2C2_ResetBusy();
    I2C_InitStructure.BusMode     = I2C_BUSMODE_I2C;
    I2C_InitStructure.FmDutyCycle = I2C_FMDUTYCYCLE_2;
    I2C_InitStructure.AckEnable   = I2C_ACKEN;
    I2C_InitStructure.AddrMode    = I2C_ADDR_MODE_7BIT;
    I2C_InitStructure.ClkSpeed    = 100000;  // 100K
    I2C_Init(I2C2, &I2C_InitStructure);      // Initial and Enable I2Cx
    I2C_Enable(I2C2, ENABLE);
}

void I2C2_NVIC_Config(void)
{
    NVIC_InitType NVIC_InitStructure;

    NVIC_InitStructure.NVIC_IRQChannel    = I2C2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 0x01;
    NVIC_Init(&NVIC_InitStructure);
    NVIC_InitStructure.NVIC_IRQChannel++;  // I2Cx_ER_IRQn
    NVIC_Init(&NVIC_InitStructure);
    I2C_ConfigInt(I2C2, I2C_INT_EVENT | I2C_INT_BUF | I2C_INT_ERR, NVIC_InitStructure.NVIC_IRQChannelCmd);
}

void I2C2_ResetInit()
{
    I2C2_Config();
    I2C2_NVIC_Config();  // #define I2Cx_UseIT
}

/**
 * =======================================================================================
 * =======================================================================================
 */
void I2C2_Initial(void)
{
    I2C2_ResetInit();
}

/**
 * @brief  Analyze the received data from upper machine through I2C bus
 * @param  data, the data buffer to be parsed
 * @return the error code
 */
static uint8_t Parse_Data(uint8_t* data)
{
    uint16_t id = 0;
    uint8_t ret = 0;
    uint16_t crc16 = 0;

    if (data[0] != 0 && data[0] != 1) //0:READ, 1:WRITE
    {
        ret = UNKNOWN_ERROR;
    }
    if (data[1] > 30) //maximum data length
    {
        ret = UNKNOWN_ERROR;
    }
    crc16 = CRC16_CCITT(data, 30); //CRC16 check
    if (crc16 == ((data[31] & 0x00FF) << 8 | data[30]))
    {
        ret = NO_ERROR;
    }
    else
    {
        ret = UNKNOWN_ERROR;
    }
    id = (data[3] & 0x00FF) << 8 | data[2];
    if ((id >= R_CURRENT && id <= R_CURRENT + 7)
            || (id >= W_SWITCH && id <= W_SWITCH + 7)
            || (id >= R_OCP && id <= R_OCP + 7)
            || (id >= R_OUT_ERROR && id <= R_OUT_ERROR + 7)
            || (id == M_TYPE)
            || (id == SW_VERSION)
            || (id == R_OTP))
    {
        ret = NO_ERROR;
    }
    else
    {
        ret = UNKNOWN_ID;
    }

    return ret;
}

/**
 * @brief  process the request from the master device, the I2C2 interface
 * @param  none
 * @return none
 */
void Process_I2C2_Request(void)
{
    uint16_t id = 0;
    uint8_t ptr = 0;
    int16_t value = 0; //result
    uint8_t len = 0;
    uint8_t i = 0;
    uint16_t crc16 = 0;
    uint8_t temp = 0;
    uint8_t ret = Parse_Data(data_rx_buf);
    if (ret == 0) //no error, in most cases
    {
        id = (data_rx_buf[3] & 0x00FF) << 8 | data_rx_buf[2];
        switch (id)
        {
            case W_SWITCH+0:        //ON/OFF control
            case W_SWITCH+1:
            case W_SWITCH+2:
            case W_SWITCH+3:
            case W_SWITCH+4:
            case W_SWITCH+5:
            case W_SWITCH+6:
            case W_SWITCH+7:
                value = Set_IOUT_Switch(id - W_SWITCH, data_rx_buf[4]); //data_rx_buf[4] is ON/OFF byte
                len = 5;
                temp = 0;
                break;
            case R_OCP+0:           //OCP
            case R_OCP+1:
            case R_OCP+2:
            case R_OCP+3:
            case R_OCP+4:
            case R_OCP+5:
            case R_OCP+6:
            case R_OCP+7:
                value = Get_OCP_Status(id - R_OCP);
                len = 5;
                temp = 0;
                break;
            case R_CURRENT+0:       //output current
            case R_CURRENT+1:
            case R_CURRENT+2:
            case R_CURRENT+3:
            case R_CURRENT+4:
            case R_CURRENT+5:
            case R_CURRENT+6:
            case R_CURRENT+7:
                value = Get_IOUT_Value(id - R_CURRENT);
                len = 6;
                temp = 0;
                break;
            case R_OUT_ERROR+0:     //Output Error
            case R_OUT_ERROR+1:
            case R_OUT_ERROR+2:
            case R_OUT_ERROR+3:
            case R_OUT_ERROR+4:
            case R_OUT_ERROR+5:
            case R_OUT_ERROR+6:
            case R_OUT_ERROR+7:
                value = Get_VOUT_Status(id - R_OUT_ERROR);
                len = 5;
                temp = 0;
                break;
			case R_TEMP:			//temperature data
				value = TMP_OUT;
				len = 5;
				temp = 0;
				break;
			/*
            case R_PIN_STATUS+0:    //Pin status(OFF1 - OFF8)
            case R_PIN_STATUS+1:
            case R_PIN_STATUS+2:
            case R_PIN_STATUS+3:
            case R_PIN_STATUS+4:
            case R_PIN_STATUS+5:
            case R_PIN_STATUS+6:
            case R_PIN_STATUS+7:
                value = Get_IOUT_Switch(id - R_PIN_STATUS);
                len = 5;
                temp = 0;
                break;
			*/
            case M_TYPE:            //module type
                len = 24;
                temp = strlen(m_type);
                break;
            case SW_VERSION:        //software version
                len = 24;
                temp = strlen(sw_version);
                break;
            case R_OTP:             //over temperature
                value = AlarmStatus.alarm.OTP;
                len = 5;
                temp = 0;
                break;
            default:
                break;
        }
        data_tx_buf[ptr++] = NO_ERROR;
        data_tx_buf[ptr++] = len;           //valid data length = ACK + LENGTH + ID + Valid Value
        data_tx_buf[ptr++] = data_rx_buf[2]; //ID
        data_tx_buf[ptr++] = data_rx_buf[3];
        if (len == 5 || len == 6)           //valid value of current, OCP or output status
        {
            data_tx_buf[ptr++] = value % 256;
            data_tx_buf[ptr++] = value >> 8;
            //for (i = len; i < 30; i++)
            for (i = 6; i < 30; i++)      //bytes to be filled with 0, total: 24 bytes
            {
                data_tx_buf[ptr++] = 0;
            }
        }
        else                                //valid value of module type or software version
        {
            if (id == M_TYPE)
            {
                for (i = 0; i < strlen(m_type); i++)
                {
                    data_tx_buf[ptr++] = m_type[i];
                }
            }
            else
            {
                for (i = 0; i < strlen(sw_version); i++)
                {
                    data_tx_buf[ptr++] = sw_version[i];
                }
            }
            for (i = 4 + temp; i < 30; i++) //bytes to be filled with 0 at the end of the module type or software version
            {
                data_tx_buf[ptr++] = 0;
            }
        }
        //calculate the CRC16
        crc16 = CRC16_CCITT(data_tx_buf, ptr);
        data_tx_buf[ptr++] = crc16 % 256;
        data_tx_buf[ptr++] = crc16 >> 8;
    }
    else
    {
        data_tx_buf[ptr++] = ret; //ACK
        data_tx_buf[ptr++] = 4; //no valid value, ACK+LENGTH+ID
        data_tx_buf[ptr++] = data_rx_buf[2]; //ID
        data_tx_buf[ptr++] = data_rx_buf[3];
        for (i = 4; i < 30; i++) //bytes to be filled with 0
        {
            data_tx_buf[ptr++] = 0;
        }
        crc16 = CRC16_CCITT(data_tx_buf, ptr);
        data_tx_buf[ptr++] = crc16 % 256;
        data_tx_buf[ptr++] = crc16 >> 8;
    }
}

/**
 * @brief  I2Cx main process
 * @param none
 */
void Process_I2C2(void)
{
    if (AlarmStatus.alarm.I2C2_NEW_REQ)
    {
        Process_I2C2_Request();
        AlarmStatus.alarm.I2C2_NEW_REQ = 0;
        AlarmStatus.alarm.I2C2_REQ_PROCESSED = 1;
    }
}

/**
 * @brief  I2Cx interrupt callback function
 * @param I2Cx I2C2
 */
void I2C2_IRQHandler(void)
{
    uint32_t last_event = I2C_GetLastEvent(I2C2);
    if ((last_event & I2C_ROLE_MASTER) != I2C_ROLE_MASTER)
    {
        switch (last_event) {
            /* Slave Tx */
            case I2C_EVT_SLAVE_SEND_ADDR_MATCHED:  // 0x00060082.EV1.EV3_1 (ADDRF TXDATE), the slave address(read) sent by the master is matched, then we can send out the first byte to the master.
                iicSlave2.ptr2 = 0;
                if (AlarmStatus.alarm.I2C2_REQ_PROCESSED)
                {
                    I2C_SendData(I2C2, data_tx_buf[iicSlave2.ptr2++]);//send the first byte
                }
                else
                {
                    I2C_SendData(I2C2, 0xFF);  //send dummy data to clear TXDATE flag
                }
                break;

            //the master wants to read the next byte from slave device
            case I2C_EVT_SLAVE_DATA_SENDING:       // 0x00060080.EV3 (TXDATE)
            case I2C_EVT_SLAVE_DATA_SENDED:        // 0x00060084.EV3_2 (TXDATE BSF)
                if (AlarmStatus.alarm.I2C2_REQ_PROCESSED) //the received request has been processed and now we send out the result to the master.
                {
                    if (iicSlave2.ptr2 < IIC_Slave_BufSize)
                    {
                        I2C_SendData(I2C2, data_tx_buf[iicSlave2.ptr2++]); //send data and clear TXDATE flag
                    }
                    else
                    {
                        AlarmStatus.alarm.I2C2_REQ_PROCESSED = 0;
                        iicSlave2.ptr2 = 0;
                        I2C_SendData(I2C2, 0xFF);  //send dummy data to clear TXDATE flag
                    }
                }
                else
                {
                    I2C_SendData(I2C2, 0xFF);  //send dummy data to clear TXDATE flag
                }
                break;

            /* Slave Rx */
            //The slave address(write) sent by the master is matched, here we are prepare for the coming data.
            case I2C_EVT_SLAVE_RECV_ADDR_MATCHED:  // 0x00020002.EV1 (ADDRF),
                iicSlave2.ptr = 0;
                //I2C_RecvData(I2C2);
                break;

            //The slave has received data from the master and all here we need to do is to save all of them.
            case I2C_EVT_SLAVE_DATA_RECVD:  // 0x00020040.EV2 (RXDATNE)
                if (iicSlave2.ptr < IIC_Slave_BufSize)
                {
                    iicSlave2.buf[iicSlave2.ptr++] = I2C_RecvData(I2C2);  //receive data and clear RXDATNE flag
                    //iicSlave2.bufSt                = 1;   //data is updating now...
                }
                else
                {
                    I2C_RecvData(I2C2);  // read data to clear RXDATNE flag
                }
                break;

            //The master sends out a STOP condition to end the communication and release the BUS.
            case I2C_EVT_SLAVE_STOP_RECVD:   // 0x00000010.EV4 (STOPF)
                I2C_Enable(I2C2, ENABLE);    // clear STOPF flag
                if (iicSlave2.ptr >= IIC_Slave_BufSize) //write command from the master, a package of 32 bytes
                {
                    uint8_t i = 0;
                    AlarmStatus.alarm.I2C2_NEW_REQ = 1; // The STOPF bit is not set after a NACK reception
                    for (i = 0; i < IIC_Slave_BufSize; i++)
                    {
                        data_rx_buf[i] = iicSlave2.buf[i];
                    }
                    for (i = 0; i < IIC_Slave_BufSize; i++) //clear the receive buffer
                    {
                        iicSlave2.buf[i] = 0x00;
                    }
                }
				AlarmStatus.alarm.I2C2_REQ_PROCESSED = 0;
				iicSlave2.ptr2 = 0;
                iicSlave2.ptr = 0;
                break;
            default:
                I2C2_ResetInit();
                break;
        }
    }
    //EV3_2: When the master sends a NACK in order to tell slave that data transmission
    //shall end (before sending the STOP condition). In this case slave has to stop sending
    //data bytes and expect a Stop condition on the bus.
    //主机在发送STOP之前发送了一个NACK给从机,表示数据传输结束(主机接收完从机发送的数据,从机停止发送数据并等待主机发送STOP)
    if (last_event == I2C_EVT_SLAVE_ACK_MISS)
    {
        I2C_ClrFlag(I2C2, I2C_FLAG_ACKFAIL);
        if (iicSlave2.ptr2 != 0) //从机已发送最后一个数据并从主机收到NACK
        {
            flag_slave_send_finish = 1;//发送完成标志
        }
        else //还没有发送完数据就收到主机的NACK,产生EV3_2事件,表示发送出错
        {

        }
    }
}

void CommTimeOut_CallBack(ErrCode_t errcode)
{
    //log_info("...ErrCode:%d\r\n", errcode);

#if (COMM_RECOVER_MODE == MODULE_SELF_RESET)
    IIC_SWReset();
#elif (COMM_RECOVER_MODE == MODULE_RCC_RESET)
    IIC_RCCReset();
#elif (COMM_RECOVER_MODE == SYSTEM_NVIC_RESET)
    SystemNVICReset();
#endif
}




//**************************** CAN BE EXECUTED CORRECTLY*************************
//#include "n32g031_i2c.h"
//#include "n32g031.h"
//#include "i2c_slave.h"
//#include "main.h"

//uint8_t data_rx_buf[BUFFER_SIZE] = {0};//data buffer
//uint8_t data_tx_buf[BUFFER_SIZE] = {0};//data buffer for I2C2
//static __IO uint32_t I2CTimeout;
//uint8_t flag_slave_recv_finish = 0;//received flag
//uint8_t flag_slave_send_finish = 0;//transmitted flag
static uint8_t rxDataNum = 0; //data length received
static uint8_t txDataNum = 0; //data length transmitted

static uint8_t RCC_RESET_Flag = 0;
static uint8_t fb_status = 0x00;//status

//volatile uint8_t iic_send_buffer[BUFFER_SIZE];

//void CommTimeOut_CallBack(ErrCode_t errcode);

//volatile _iicMaster iicMaster;  // useIT for master
//volatile _iicSlave iicSlave;    // useIT for I2C1
//volatile _iicSlave iicSlave2;	// useIT for I2C2

///**
// * =======================================================================================
// * =======================================================================================
// */

//void I2C1_ResetBusy()
//{
//    I2C1->CTRL1 |= 0x8000;  // Reset Busy
//    __NOP();
//    __NOP();
//    __NOP();
//    __NOP();
//    __NOP();
//    I2C1->CTRL1 &= ~0x8000;
//}

//void I2C1_Config(void)
//{
//    I2C_InitType I2C_InitStructure;
//    //I2C_InitType i2c1_slave;
//    GPIO_InitType i2c1_gpio;
//    //RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_I2C1, ENABLE);
//    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);
//    
//    GPIO_InitStruct(&i2c1_gpio);
//    //PB6 -- SCL; PB7 -- SDA
//    i2c1_gpio.Pin        = I2Cx_SCL_PIN | I2Cx_SDA_PIN;
//    i2c1_gpio.GPIO_Speed = GPIO_SPEED_HIGH;
//    i2c1_gpio.GPIO_Mode  = GPIO_MODE_AF_OD;//alternate open-drain
//    i2c1_gpio.GPIO_Alternate = GPIO_AF_I2C;
//    GPIO_InitPeripheral(GPIOx, &i2c1_gpio);    
//    
//    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_I2C1, ENABLE);
//    I2C_InitStructure.OwnAddr1 = I2C_SLAVE_ADDR;     
//    I2C_DeInit(I2C1);
//    I2C1_ResetBusy();
//    I2C_InitStructure.BusMode     = I2C_BUSMODE_I2C;
//    I2C_InitStructure.FmDutyCycle = I2C_FMDUTYCYCLE_2;
//    I2C_InitStructure.AckEnable   = I2C_ACKEN;
//    I2C_InitStructure.AddrMode    = I2C_ADDR_MODE_7BIT;
//    I2C_InitStructure.ClkSpeed    = 100000;  // 100K
//    I2C_Init(I2C1, &I2C_InitStructure);      // Initial and Enable I2Cx
//    I2C_Enable(I2C1, ENABLE);
//}

//void I2C1_NVIC_Config(void)
//{
//    NVIC_InitType NVIC_InitStructure;
//    
//	NVIC_InitStructure.NVIC_IRQChannel    = I2C1_IRQn;
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    
//    NVIC_InitStructure.NVIC_IRQChannelPriority = 0x01;    
//    NVIC_Init(&NVIC_InitStructure);
//    NVIC_InitStructure.NVIC_IRQChannel++;  // I2Cx_ER_IRQn
//    NVIC_Init(&NVIC_InitStructure);
//    I2C_ConfigInt(I2C1, I2C_INT_EVENT | I2C_INT_BUF | I2C_INT_ERR, NVIC_InitStructure.NVIC_IRQChannelCmd);
//}

//void I2C1_ResetInit()
//{
//    I2C1_Config();
//    I2C1_NVIC_Config();  // #define I2Cx_UseIT
//}

///**
// * =======================================================================================
// * =======================================================================================
// */
//void I2C1_Initial(void)
//{
//    I2C1_ResetInit();
//}

///**
// * @brief  I2Cx interrupt callback function
// * @param I2Cx I2C1
// */
void I2C_EV_IRQ_CallBack(volatile _iicMaster* iicMaster, volatile _iicSlave* iicSlave)
//void I2C1_IRQHandler(void)
//{
//    uint32_t last_event = I2C_GetLastEvent(I2C1);
//    if ((last_event & I2C_ROLE_MASTER) != I2C_ROLE_MASTER)
//    {
//        switch (last_event) {
//                /* Slave Tx */
//            case I2C_EVT_SLAVE_SEND_ADDR_MATCHED:  // 0x00060082.EV1.EV3_1 (ADDRF TXDATE)
//            case I2C_EVT_SLAVE_DATA_SENDING:       // 0x00060080.EV3 (TXDATE)
//            case I2C_EVT_SLAVE_DATA_SENDED:        // 0x00060084.EV3_2 (TXDATE BSF)
//                /*
//                if (iicSlave.ptr < IIC_Slave_BufSize) {
//                    I2C_SendData(I2C1, iicSlave.buf[iicSlave.ptr++]);  // clear TXDATE
//                } else {
//                    I2C_SendData(I2C1, 0xFF);  // clear TXDATE
//                }
//                */
//                switch(iicSlave.buf[0])
//				{
//					case PSU_INFO:
//						if (iicSlave.ptr < IIC_Slave_BufSize) {
//							//I2C_SendData(I2C1, iicSlave.buf[iicSlave.ptr++]);  // clear TXDATE
//							I2C_SendData(I2C1, iic_send_buffer[iicSlave.ptr++]);  // clear TXDATE
//						} else {
//							I2C_SendData(I2C1, 0xFF);  // clear TXDATE
//						}
//						break;
//					default:
//						data_rx_buf[0]=0x00;
//						I2C1->DAT=0xFF;
//						break;
//                }
//                break;
//                /* Slave Rx */
//            case I2C_EVT_SLAVE_RECV_ADDR_MATCHED:  // 0x00020002.EV1 (ADDRF)
//                iicSlave.ptr = 0;
//                if (IIC_Slave_BufSize > 256) {
//                    iicSlave.ptrSt = 1;  //
//                } else {
//                    iicSlave.ptrSt = 2;  //
//                }
//				//I2C_RecvData(I2C1);
//                break;
//            case I2C_EVT_SLAVE_DATA_RECVD:  // 0x00020040.EV2 (RXDATNE)
//                switch (iicSlave.ptrSt) {
//                    case 1:                                                  //实际并未执行case 1
//                        iicSlave.ptr   = (uint16_t)I2C_RecvData(I2C1) << 8;  // clear RXDATNE
//                        iicSlave.ptrSt = 2;                                  //
//                        break;
//                    case 2:                                   // 写ptr高字节
//                        //iicSlave.ptr += I2C_RecvData(I2C1);  // clear RXDATNE  //commented by Power on March 3rd, 2023
//                        //iicSlave.ptrSt = 3;                  //准备写buf数据
//                        //break;
//                    case 3: 
//                        if (iicSlave.ptr < IIC_Slave_BufSize) {
//                            iicSlave.buf[iicSlave.ptr++] = I2C_RecvData(I2C1);  // clear RXDATNE
//                            iicSlave.bufSt                = 1;	//data is updating now...
//                        } else {
//                            I2C_RecvData(I2C1);  // clear RXDATNE
//                        }                        
//                        break;
//                    default:
//                        I2C_RecvData(I2C1);  // clear RXDATNE
//                        break;
//                }
//                break;
//            case I2C_EVT_SLAVE_STOP_RECVD:   // 0x00000010.EV4 (STOPF)
//				iicSlave.ptr=0;
//                I2C_Enable(I2C1, ENABLE);    // clear STOPF
//                if (iicSlave.bufSt == 1) { 
//                    iicSlave.bufSt = 2;		//data updating is complete
//                }
//				/*======here we don't have any operation from upper machine
//				switch(iicSlave.buf[0])
//				{
//					case OUTPUT_CONTROL:
//						Set_Output_Switch(iicSlave.buf[1]);
//						//iicSlave.buf[1]=0xFF;
//						break;
//					default:
//						//iicSlave.buf[0]=0x00;
//						break;
//				}*/
//                break;
//            default:
//                I2C1_ResetInit();
//                break;
//        }
//    }
//}

/**
 * @brief  i2c slave Interrupt service function
 */
void I2C1_IRQHandler_Backup(void)
{
    uint8_t timeout_flag = 0;
    uint32_t last_event = 0;	
    
    last_event = I2C_GetLastEvent(I2C1);
	if ((last_event & I2C_ROLE_MASTER) != I2C_ROLE_MASTER) // MSMODE = 0:I2C slave mode
    {
        switch (last_event)
        {
			//EV1: 主机发送的地址与本从机地址匹配(从机准备接收数据,也就是主机要发送数据给从机)
			case I2C_EVT_SLAVE_RECV_ADDR_MATCHED: //0x00020002.EV1 Rx addr matched				
				//clear flag,ready to receive data
				rxDataNum = 0;
				break;
			
			//EV1: 主机发送的地址与本从机地址匹配(主机要从从机获取数据,从机开始发送第一个数据给主机)
			case I2C_EVT_SLAVE_SEND_ADDR_MATCHED: //0x00060082.EV1 Tx addr matched				
				txDataNum = 0;
				rxDataNum = 0;
				switch(data_rx_buf[0])
				{
					case OUTPUT_CONTROL:
						//I2C1->DAT = fb_status;
						I2C1->DAT = 0x00;
						break;					
					case OUTPUT_VOLTAGE_HIGH: //test purpose
						I2C1->DAT = VOS_OUT>>8;
						break;
					case OUTPUT_VOLTAGE_LOW: //test purpose
						I2C1->DAT = (uint8_t)VOS_OUT;
						break;
					
					default:
						data_rx_buf[0]=0x00;
						I2C1->DAT=0xFF;
						break;
				}				
				break;
			
			//EV3: SlaveTransmitter,数据正在发送中,此事件和I2C_EVT_SLAVE_DATA_SENDED类似	
			case I2C_EVT_SLAVE_DATA_SENDING:  //0x00060080. EV3 Sending data			   
				break;
			
			//EV3: 从机发送一个数据成功,收到主机回应后接着发送下一个数据(只有返回电流值时才会发送多个字节)
			case I2C_EVT_SLAVE_DATA_SENDED:						
				break;
			
			//EV2: SlaveReceiver,从机接收到并保存从主机发送来的数据
			case I2C_EVT_SLAVE_DATA_RECVD: //0x00020040.EV2 one byte recved
				if(rxDataNum < BUFFER_SIZE)
				{
					data_rx_buf[rxDataNum++] = I2C1->DAT;
				}
				break; 
			
			//EV4: When the application is expecting the end of the communication: master sends a stop condition and data transmission is stopped.
			//表示应用程序希望结束通信,也就是说EV4表明主机发送了一个STOP停止信号,从机接收数据完成
			case I2C_EVT_SLAVE_STOP_RECVD: // 0x00000010 EV4
				I2C_Enable(I2C1, ENABLE);   
				if(rxDataNum != 0)
				{
					flag_slave_recv_finish = 1; // The STOPF bit is not set after a NACK reception
				}
				switch(data_rx_buf[0])
				{
					//case OUTPUT_CONTROL:
						//Set_Output_Switch(data_rx_buf[1]);
						//data_rx_buf[1]=0xFF;
						//break;
					default:
						data_rx_buf[0]=0x00;
						break;
				}
				break;
			
			default:
				I2C_Enable(I2C1, ENABLE);
				timeout_flag = 1;
				break;
        }
    }
    
    if (timeout_flag)//出现超时错误则根据错误代码重启I2C模块
    {
        if ((I2CTimeout--) == 0)
        {
            CommTimeOut_CallBack(SLAVE_UNKNOW);
        }
    }
    else
    {
        I2CTimeout = I2CT_LONG_TIMEOUT;
    }
	
	//EV3_2: When the master sends a NACK in order to tell slave that data transmission
	//shall end (before sending the STOP condition). In this case slave has to stop sending
	//data bytes and expect a Stop condition on the bus.
	//主机在发送STOP之前发送了一个NACK给从机,表示数据传输结束(主机接收完从机发送的数据,从机停止发送数据并等待主机发送STOP)
    if(last_event == I2C_EVT_SLAVE_ACK_MISS)   
    {   
        I2C_ClrFlag(I2C1, I2C_FLAG_ACKFAIL);
        if(txDataNum != 0)  //从机已发送最后一个数据并从主机收到NACK
        {
            flag_slave_send_finish = 1;//发送完成标志
        }
        else //还没有发送完数据就收到主机的NACK,产生EV3_2事件,表示发送出错
        {
			
        }
    }
}

///**
// * =======================================================================================
// * =======================================================================================
// */

//void I2C2_ResetBusy()
//{
//    I2C2->CTRL1 |= 0x8000;  // Reset Busy
//    __NOP();
//    __NOP();
//    __NOP();
//    __NOP();
//    __NOP();
//    I2C2->CTRL1 &= ~0x8000;
//}

///**
//*@name: I2C2_Config
//*@description: for the main communication with the upper machine
//*@input: none
//*@output: none
//**/
//void I2C2_Config(void)
//{
//    I2C_InitType I2C_InitStructure;
//    //I2C_InitType i2c1_slave;
//    GPIO_InitType i2c1_gpio;
//    //RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_I2C1, ENABLE);
//    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
//    
//    GPIO_InitStruct(&i2c1_gpio);
//    //PA9 -- SCL; PA10 -- SDA
//    i2c1_gpio.Pin        = I2C2_SCL_PIN | I2C2_SDA_PIN;
//    i2c1_gpio.GPIO_Speed = GPIO_SPEED_HIGH;
//    i2c1_gpio.GPIO_Mode  = GPIO_MODE_AF_OD;//alternate open-drain
//    i2c1_gpio.GPIO_Alternate = GPIO_AF_I2C2;
//    GPIO_InitPeripheral(GPIOx, &i2c1_gpio);    
//    
//    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_I2C2, ENABLE);
//    I2C_InitStructure.OwnAddr1 = I2C2_SLAVE_ADDR;     
//    I2C_DeInit(I2C2);
//    I2C2_ResetBusy();
//    I2C_InitStructure.BusMode     = I2C_BUSMODE_I2C;
//    I2C_InitStructure.FmDutyCycle = I2C_FMDUTYCYCLE_2;
//    I2C_InitStructure.AckEnable   = I2C_ACKEN;
//    I2C_InitStructure.AddrMode    = I2C_ADDR_MODE_7BIT;
//    I2C_InitStructure.ClkSpeed    = 100000;  // 100K
//    I2C_Init(I2C2, &I2C_InitStructure);      // Initial and Enable I2Cx
//    I2C_Enable(I2C2, ENABLE);
//}

//void I2C2_NVIC_Config(void)
//{
//    NVIC_InitType NVIC_InitStructure;
//    
//	NVIC_InitStructure.NVIC_IRQChannel    = I2C2_IRQn;
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    
//    NVIC_InitStructure.NVIC_IRQChannelPriority = 0x01;    
//    NVIC_Init(&NVIC_InitStructure);
//    NVIC_InitStructure.NVIC_IRQChannel++;  // I2Cx_ER_IRQn
//    NVIC_Init(&NVIC_InitStructure);
//    I2C_ConfigInt(I2C2, I2C_INT_EVENT | I2C_INT_BUF | I2C_INT_ERR, NVIC_InitStructure.NVIC_IRQChannelCmd);
//}

//void I2C2_ResetInit()
//{
//    I2C2_Config();
//    I2C2_NVIC_Config();  // #define I2Cx_UseIT
//}

///**
// * =======================================================================================
// * =======================================================================================
// */
//void I2C2_Initial(void)
//{
//    I2C2_ResetInit();
//}


//static void Parse_Data()
//{
//	
//}

///**
// * @brief  I2Cx interrupt callback function
// * @param I2Cx I2C2
// */
//void I2C2_IRQHandler(void)
//{
//    uint32_t last_event = I2C_GetLastEvent(I2C2);
//    if ((last_event & I2C_ROLE_MASTER) != I2C_ROLE_MASTER)
//    {
//        switch (last_event) {
//                /* Slave Tx */
//            case I2C_EVT_SLAVE_SEND_ADDR_MATCHED:  // 0x00060082.EV1.EV3_1 (ADDRF TXDATE)
//            case I2C_EVT_SLAVE_DATA_SENDING:       // 0x00060080.EV3 (TXDATE)
//            case I2C_EVT_SLAVE_DATA_SENDED:        // 0x00060084.EV3_2 (TXDATE BSF)
//                /*
//                if (iicSlave.ptr < IIC_Slave_BufSize) {
//                    I2C_SendData(I2C1, iicSlave.buf[iicSlave.ptr++]);  // clear TXDATE
//                } else {
//                    I2C_SendData(I2C1, 0xFF);  // clear TXDATE
//                }
//                */
//                switch(iicSlave.buf[0])
//				{
//					case PSU_INFO:
//						if (iicSlave.ptr < IIC_Slave_BufSize) {
//							//I2C_SendData(I2C1, iicSlave.buf[iicSlave.ptr++]);  // clear TXDATE
//							I2C_SendData(I2C2, iic_send_buffer[iicSlave.ptr++]);  // clear TXDATE
//						} else {
//							I2C_SendData(I2C2, 0xFF);  // clear TXDATE
//						}
//						break;
//					default:
//						data_rx_buf[0]=0x00;
//						I2C2->DAT=0xFF;
//						break;
//                }
//                break;
//                /* Slave Rx */
//            case I2C_EVT_SLAVE_RECV_ADDR_MATCHED:  // 0x00020002.EV1 (ADDRF)
//                iicSlave.ptr = 0;
//                if (IIC_Slave_BufSize > 256) {
//                    iicSlave.ptrSt = 1;  //
//                } else {
//                    iicSlave.ptrSt = 2;  //
//                }
//				//I2C_RecvData(I2C1);
//                break;
//            case I2C_EVT_SLAVE_DATA_RECVD:  // 0x00020040.EV2 (RXDATNE)
//                switch (iicSlave.ptrSt) {
//                    case 1:                                                  //实际并未执行case 1
//                        iicSlave.ptr   = (uint16_t)I2C_RecvData(I2C2) << 8;  // clear RXDATNE
//                        iicSlave.ptrSt = 2;                                  //
//                        break;
//                    case 2:                                   // 写ptr高字节
//                        //iicSlave.ptr += I2C_RecvData(I2C1);  // clear RXDATNE  //commented by Power on March 3rd, 2023
//                        //iicSlave.ptrSt = 3;                  //准备写buf数据
//                        //break;
//                    case 3: 
//                        if (iicSlave.ptr < IIC_Slave_BufSize) {
//                            iicSlave.buf[iicSlave.ptr++] = I2C_RecvData(I2C2);  // clear RXDATNE
//                            iicSlave.bufSt                = 1;	//data is updating now...
//                        } else {
//                            I2C_RecvData(I2C2);  // clear RXDATNE
//                        }                        
//                        break;
//                    default:
//                        I2C_RecvData(I2C2);  // clear RXDATNE
//                        break;
//                }
//                break;
//            case I2C_EVT_SLAVE_STOP_RECVD:   // 0x00000010.EV4 (STOPF)
//				iicSlave.ptr=0;
//                I2C_Enable(I2C2, ENABLE);    // clear STOPF
//                if (iicSlave.bufSt == 1) { 
//                    iicSlave.bufSt = 2;		//data updating is complete
//                }				
//                break;
//            default:
//                I2C2_ResetInit();
//                break;
//        }
//    }
//}

//void CommTimeOut_CallBack(ErrCode_t errcode)
//{
//    //log_info("...ErrCode:%d\r\n", errcode);
//    
//#if (COMM_RECOVER_MODE == MODULE_SELF_RESET)
//    IIC_SWReset();
//#elif (COMM_RECOVER_MODE == MODULE_RCC_RESET)
//    IIC_RCCReset();
//#elif (COMM_RECOVER_MODE == SYSTEM_NVIC_RESET)
//    SystemNVICReset();
//#endif
//}


14、i2c_slave.h

#ifndef __I2C_SLAVE_H__
#define __I2C_SLAVE_H__

#include "n32g031.h"

#define I2Cx 				I2C1
#define I2Cx_SCL_PIN 		GPIO_PIN_6
#define I2Cx_SDA_PIN 		GPIO_PIN_7
#define I2C_SLAVE_ADDR  	(0x5E<<1)
#define GPIOx        		GPIOB
#define GPIO_AF_I2C 		GPIO_AF6_I2C1
#define I2C2_SCL_PIN 		GPIO_PIN_9
#define I2C2_SDA_PIN 		GPIO_PIN_10
#define I2C2_SLAVE_ADDR  	(0x21<<1)
#define GPIOy        		GPIOA
#define GPIO_AF_I2C2 		GPIO_AF7_I2C2	//AF7: PA9, PA10

#define BUFFER_SIZE  		32
#define IIC_Slave_BufSize 	(32)//the package size is 32
#define I2CT_FLAG_TIMEOUT 	((uint32_t)0x1000)
#define I2CT_LONG_TIMEOUT 	((uint32_t)(10 * I2CT_FLAG_TIMEOUT))

#define	PSU_INFO			0xF8

typedef enum
{
    MASTER_OK = 0,
    MASTER_BUSY,
    MASTER_MODE,
    MASTER_TXMODE,
    MASTER_RXMODE,
    MASTER_SENDING,
    MASTER_SENDED,
    MASTER_RECVD,
    MASTER_BYTEF,
    MASTER_BUSERR,
    MASTER_UNKNOW,
    SLAVE_OK = 20,
    SLAVE_BUSY,
    SLAVE_MODE,
    SLAVE_BUSERR,
    SLAVE_UNKNOW,

}ErrCode_t;

typedef struct {
    uint8_t dir;  // I2C_DIRECTION_SEND or I2C_DIRECTION_RECV
    uint8_t slaveAddr;
    short regAddr;  // -1 : no reg
    uint16_t dataLen;
    uint16_t dataCnt;
    uint8_t* datPtr;
} _iicMaster;

typedef struct {
    uint8_t buf[IIC_Slave_BufSize];  //  receive and send buffer
    uint16_t ptr;                    //  receive pointer
	uint16_t ptr2;					 //	 transmit pointer
    uint8_t bufSt;                   
    uint8_t ptrSt;                   
} _iicSlave;

extern volatile _iicMaster iicMaster;
extern volatile _iicSlave iicSlave;

#define MODULE_SELF_RESET       1
#define MODULE_RCC_RESET        2
#define SYSTEM_NVIC_RESET       3
#define COMM_RECOVER_MODE       0

int I2C_Slave_Init(void);
void I2C1_Initial(void);
void I2C2_Initial(void);
void Set_Output_Switch(uint8_t cmd);
void Process_I2C2_Request(void);
void Process_I2C2(void);
#endif



//***********************BACK UP CAN BE EXECUTED CORRECTLY*********************
//#ifndef __I2C_SLAVE_H__
//#define __I2C_SLAVE_H__

//#include "n32g031.h"

//#define I2Cx 				I2C1
//#define I2Cx_SCL_PIN 		GPIO_PIN_6
//#define I2Cx_SDA_PIN 		GPIO_PIN_7
//#define I2C_SLAVE_ADDR  	(0x5E<<1)
//#define GPIOx        		GPIOB
//#define GPIO_AF_I2C 		GPIO_AF6_I2C1
//#define I2C2_SCL_PIN 		GPIO_PIN_9
//#define I2C2_SDA_PIN 		GPIO_PIN_10
//#define I2C2_SLAVE_ADDR  	(0x6E<<1)
//#define GPIOy        		GPIOA
//#define GPIO_AF_I2C2 		GPIO_AF7_I2C2	//AF7: PA9, PA10

//#define BUFFER_SIZE  		32
//#define IIC_Slave_BufSize 	(32)//actually we send out only 16 bytes
//#define I2CT_FLAG_TIMEOUT 	((uint32_t)0x1000)
//#define I2CT_LONG_TIMEOUT 	((uint32_t)(10 * I2CT_FLAG_TIMEOUT))


//#define	PSU_INFO				0xF8
//#define	SHORT_STATUS			0xA0
//#define	OUTPUT_STATUS			0xB0
//#define	OUTPUT_VOLTAGE_HIGH		0xC0
//#define	OUTPUT_VOLTAGE_LOW		0xC1

//typedef enum
//{
//    MASTER_OK = 0,
//    MASTER_BUSY,
//    MASTER_MODE,
//    MASTER_TXMODE,
//    MASTER_RXMODE,
//    MASTER_SENDING,
//    MASTER_SENDED,
//    MASTER_RECVD,
//    MASTER_BYTEF,
//    MASTER_BUSERR,
//    MASTER_UNKNOW,
//    SLAVE_OK = 20,
//    SLAVE_BUSY,
//    SLAVE_MODE,
//    SLAVE_BUSERR,
//    SLAVE_UNKNOW,

//}ErrCode_t;

//typedef struct {
//    uint8_t dir;  // I2C_DIRECTION_SEND or I2C_DIRECTION_RECV
//    uint8_t slaveAddr;
//    short regAddr;  // -1 : no reg
//    uint16_t dataLen;
//    uint16_t dataCnt;
//    uint8_t* datPtr;
//} _iicMaster;

//typedef struct {
//    uint8_t buf[IIC_Slave_BufSize];  //  receive and send buffer
//    uint16_t ptr;                    //  send/receive pointer
//    uint8_t bufSt;                   
//    uint8_t ptrSt;                   
//} _iicSlave;

//extern volatile _iicMaster iicMaster;
//extern volatile _iicSlave iicSlave;

//#define MODULE_SELF_RESET       1
//#define MODULE_RCC_RESET        2
//#define SYSTEM_NVIC_RESET       3
//#define COMM_RECOVER_MODE       0

//int I2C_Slave_Init(void);
//void I2C1_Initial(void);
//void I2C2_Initial(void);
//void Set_Output_Switch(uint8_t cmd);
//	
//#endif

你可能感兴趣的:(单片机,嵌入式硬件)