最近使用国民技术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