华大单片机教程

入门第五步——I2C通信

由于I2C通信是单片机和I2C模块通信,如果不借用逻辑分析仪之类的工具的话,很难观测到数据的传输(考虑到初入行,没有能力购买逻辑分析仪),正好前面我们已经学习了UART通信,本次教程将通过UART串口来打印写入和读出的数据。由于我采用的是低功耗模块,所以为了芯片的最大化利用,我将采用低功耗模式来编程,UART和I2C将通过中断的方式来读写数据。另外本次采用的I2C模块是MB85RC04非易失铁电寄存器。
在这里插入图片描述
首先我们看一下这个寄存器的技术手册,查一下他的器件地址和通信流程。
在这里插入图片描述
从这张图可以看出,该寄存器的器件地址为1010XXX(),即AX(),这个括号代表写或者读。大部分器件是0写1读,这个具体得看器件手册,我这个是0写1读。另外考虑到实际的工作需求,我们采用页写和页读,这个具体的也需要查看器件手册是怎么规定的。看下图
在这里插入图片描述
这个是写多个数据,在实际项目中写一个数据的还是很少见的。
在这里插入图片描述
这个是顺序读,简单概括也就是读多个数据,且按照给定的读的地址依次往后读取给定的长度。

话说回来再讲一下通信原理:I2C 总线使用连接设备的"SCL"(串行时钟总线)和"SDA"(串行数据总线)来传送信息。主机在 SCL线上输出串行时钟信号,数据在 SDA 线上进行传输,每传输一个字节(最高位 MSB 开始传输),后面跟随一个应答位。一个 SCL 时钟脉冲传输一个数据位。通常标准 I2C 传输协议包含四个部分:起始(S)或重复起始信号(Sr),从机地址及读写位,传输数据,停止信号§。

其实I2C的通信原理并不复杂,就是上面这个流程,主机发一次消息,从机回一次消息,不回复表示没有从机响应,就结束通信或者重新发起。
讲到这里,我们还需要了解一下华大单片机的I2C状态码。看下图
在这里插入图片描述在这里插入图片描述
今天我们用到的是主发送和主接收。
下面开始写代码。
新建一个App_I2c.c和.h

/**
 ******************************************************************************
 ** \brief  I2C初始化函数
 **
 ** \return 无返回值
 **	
 **	采用硬件I2C1,传输时钟为PCLK,速率为标准速率100KHZ
 ** 
 ******************************************************************************/

#include "App_I2c_Init.h"

///< I2C 模块配置
void App_I2c_Init(void)
{
    stc_i2c_cfg_t stcI2cCfg;

    DDL_ZERO_STRUCT(stcI2cCfg);                            ///< 初始化结构体变量的值为0
    
    Sysctrl_SetPeripheralGate(SysctrlPeripheralI2c1,TRUE); ///< 开启I2C1时钟门控      

    stcI2cCfg.u32Pclk = Sysctrl_GetPClkFreq();  ///< 获取PCLK时钟
    stcI2cCfg.u32Baud = 100000;                 ///< 100KHz
    stcI2cCfg.enMode = I2cMasterMode;           ///< 主机模式
    stcI2cCfg.u8SlaveAddr = 0x55;               ///< 从地址,主模式无效
    stcI2cCfg.bGc = FALSE;                      ///< 广播地址应答使能关闭
    I2C_Init(M0P_I2C1,&stcI2cCfg);              ///< 模块初始化
    
    EnableNvic(I2C1_IRQn, IrqLevel3, TRUE);     ///< 系统中断使能
}

.h就是包含一下头文件和外部声明,这需要在初始化头文件里面调用初始化。
中断函数里面需要添加I2C中断,考虑到我们既写又读,再加上作为初学者,我们分开写函数更好,方便自己理解。
写一个I2C_PageWrite()函数和I2C_PageRead()函数,写到这我们是不是需要一个变量来说明我们是写操作还是读操作,那我们在这规定一下我们整个程序的一个流程。看下图

在这里插入图片描述
研究这个图,我们可以发现一个问题,写的过程中我们怎么知道数据是否写成功了?改进一下,我们写完就读,然后和写进去的数据进行比较,如果一样就返回0x01,不一样就返回0x00,在读过程我们也判断一下。
在这里插入图片描述
这个流程就比较完美了,写完了先验证是否真的写入。下面将流程变为现实。

过程慢慢描述进度会变慢,我这里就不多赘述,看完整代码。
这里有重新写个.c和.h(Data_treating.c和Data_treating.h)
Data_treating.c

#include "Data_treating.h"

#define I2C_SLAVEWT 0xA0					//I2C设备地址+写
#define I2C_SLAVERD 0xA1					//I2C设备地址+读
#define Return_startByte 0xFF			//反馈数据首地址
//#define u32Len Rxbuff.len-2					//I2C存储数据字节长度	
#define	Command_bit Rxbuff.u8[1]			//I2C读或写数据命令位

volatile uint8_t I2cState = 0;				//获取I2C状态
volatile uint8_t u8Addr  = 0x00;  			//FRAM地址字节
volatile uint8_t I2CState;  			//FRAM地址字节
volatile uint8_t u32Len;

FRAME_RW_t FRAME_RW;


void CheckWrite()							//检查需要写的数据和已经写入的数据是否一致
{
	for (uint8_t i=0;i<Rxbuff.len-3;i++)			
	{
		if(Rxbuff.u8[i+2]!= Rxbuff.I2[i+2])
		{
			TxBuff.buff[2]=0x00;			//TxBuff.buff[1]为标志位,0未成功写入,1成功写入
			return;
		}
		TxBuff.buff[2]=0x01;	
	}
}


void I2C_PageWrite(uint8_t *pu8Data)				///I2C按页写入(写入数据为pu8Data传入数组)
{
	I2cState = I2C_GetState(M0P_I2C1);
	u32Len =Rxbuff.len-2;							//I2c存储数据的长度为串口接收数据长度-2(0xFF和命令)
	switch(I2cState)
        {
            case 0x08:                               ///< 已发送起始条件
			{
				I2C_ClearFunc(M0P_I2C1, I2cStart_En);
                I2C_WriteByte(M0P_I2C1, I2C_SLAVEWT);   ///< 从设备地址发送
                break;
			}
            case 0x18:                               ///< 已发送SLA+W,并接收到ACK
			{
                I2C_WriteByte(M0P_I2C1, u8Addr);          ///< 从设备内存地址发送
                break;
			}
			case 0x28:									///< 上一次发送数据后接收到ACK
			{
				if(Rxbuff.idc > u32Len)
				{
					I2C_SetFunc(M0P_I2C1, I2cStop_En);       //将发送停止条件
					Rxbuff.idc = 2;
					PeriperalStatus.bitField.i2c=0;
					break;
				}
				else
				{	
					I2C_WriteByte(M0P_I2C1, Rxbuff.u8[Rxbuff.idc++]);          ///< 发送数据
					break;
				}
			}
            default:
				I2C_SetFunc(M0P_I2C1, I2cStop_En);			///< 其他错误状态,结束起始条件
                break;
        }
		I2C_ClearIrq(M0P_I2C1);                                 //清除中断状态标志位
}

void I2C_PageRead(uint8_t *pu8Data)						///I2C按页读出(读出数据到pu8Data数组)
{
	 I2cState = I2C_GetState(M0P_I2C1);
	 u32Len= Rxbuff.len-2;								//I2c读取数据的长度为串口接收数据长度-2(0xFF和命令)
	 switch(I2cState)
        {
            case 0x08:                                 ///< 已发送起始条件,将发送SLA+W
			{
				I2C_ClearFunc(M0P_I2C1,I2cStart_En);
                I2C_WriteByte(M0P_I2C1,I2C_SLAVEWT);
                break;
			}
            case 0x18:                                 ///< 已发送SLA+W,并接收到ACK
			{
				I2C_WriteByte(M0P_I2C1,u8Addr);            ///< 发送从机内存地址
                break;
			}
            case 0x28:                                 ///< 已发送数据,接收到ACK
			{
				I2C_SetFunc(M0P_I2C1,I2cStart_En);         ///< 发送重复起始条件
                break;
			}
            case 0x10:                                 ///< 已发送重复起始条件
			{
				I2C_ClearFunc(M0P_I2C1,I2cStart_En);
                I2C_WriteByte(M0P_I2C1,I2C_SLAVERD);///< 发送SLA+R,开始从从机读取数据
                break;
			}
            case 0x40:                               ///< 已发送SLA+R,并接收到ACK
			{
				if(1 < (u32Len))
				{
					I2C_SetFunc(M0P_I2C1, I2cAck_En);            //读取数据超过1个字节才发送ACK
				}
				break;
			}
            case 0x50:                                 ///< 已接收数据字节,并已返回ACK信号
			{
				pu8Data[Rxbuff.idc++] = I2C_ReadByte(M0P_I2C1);
                if(Rxbuff.idc==u32Len)
                {
                    I2C_ClearFunc(M0P_I2C1,I2cAck_En);     ///< 已接收到倒数第二个字节,关闭ACK应答功能
                }
                break;
			}
            case 0x58:                                 ///< 已接收到最后一个数据,NACK已返回
			{
				pu8Data[Rxbuff.idc++] = I2C_ReadByte(M0P_I2C1);
				I2C_SetFunc(M0P_I2C1,I2cStop_En);          ///< 发送停止条件
				Rxbuff.idc = 2;
				Rxbuff.idt = 0;
				Rxbuff.u8[1]=Rxbuff01;
				PeriperalStatus.bitField.i2c=0;
                break;
			}
            default:
				I2C_SetFunc(M0P_I2C1, I2cStop_En);			///< 其他错误状态,结束起始条件
                break;
        }
		I2C_ClearIrq(M0P_I2C1);                                 //清除中断状态标志位
}

void SendData_ToPc(void)
{
	switch(Command_bit)
	{
		case FRAME_Write:								// 写操作
		{
			FRAME_RW=FRAME_Write;
			CheckWrite();								// 写成功,进行数据校验
			TxBuff.buff[0]=Return_startByte;			//反馈数组首字节
			TxBuff.buff[1]=FRAME_RW;
			TxBuff.buff[3]=XoRCheck(TxBuff.buff, 3);
			LPUart_SendDataIt(M0P_LPUART1, TxBuff.buff[TxBuff.idx]); 	// 发送第一个字节
			break;
		}
		case FRAME_Read:
		{
			FRAME_RW=FRAME_Read;						// 读操作
			Rxbuff.idc = 0;
			Rxbuff.I2[0]=Return_startByte;				//反馈数组首字节
			Rxbuff.I2[1]=FRAME_RW;
			Rxbuff.I2[Rxbuff.len-1]=XoRCheck(Rxbuff.I2, Rxbuff.len-1); // IIC读数据,BCC校验存储位
			LPUart_SendDataIt(M0P_LPUART1, Rxbuff.I2[Rxbuff.idc]);
			break;
		}
	}
}

void LpUart_Send(void)
{
	switch(Command_bit)
	{
		case FRAME_Write:				// 写操作
		{
			if(TxBuff.idx<3)			// 回传PC数据有3个,如果TxBuff.idx小于3继续发送
			{
				LPUart_SendDataIt(M0P_LPUART1, TxBuff.buff[++TxBuff.idx]);
				break;
			}
				TxBuff.idx = 0;
				break;
		}
		case FRAME_Read:
		{
			if( Rxbuff.idc < Rxbuff.len-1)
			{
				LPUart_SendDataIt(M0P_LPUART1, Rxbuff.I2[++Rxbuff.idc]);
				break;
			}
				Rxbuff.idc = 0;
				break;
		}
	}
}


Data_treating.h

#ifndef __DATA_TREATING_H__
#define __DATA_TREATING_H__

#include "Sys_Init.h"

// 定义FRAME_RW_t枚举类型,用于表示IIC读写操作
typedef enum{
	FRAME_Read = 1,	 					// 读操作
	FRAME_Write = 0						// 写操作
}__attribute__((packed)) FRAME_RW_t;


void I2C_PageWrite(uint8_t *pu8Data);	// TODO: 实现I2C页写功能
void I2C_PageRead(uint8_t *pu8Data); 	// TODO: 实现I2C页读功能
void SendData_ToPc(void); 				// TODO: 实现将数据发送到PC端的功能
void LpUart_Send(void);					// 发送数据到LPUART接口

#endif


main.c

#include "main.h"

TxBuf TxBuff;
SystemStatus_t SystemStatus;
PeripheralStatus_t PeriperalStatus;


int32_t main()
{    
	delay1ms(2000);
	
	Sys_Init();
	
    while(1)
	{
		switch(SystemStatus)
		{
			case RxCompleteState:		//串口写数据到单片机,写完成标志状态1
			{
				if(Rxbuff.u8[Rxbuff.len-1] == XoRCheck(Rxbuff.u8, Rxbuff.len-1))
				{
					PeriperalStatus.bitField.i2c=1;
					I2C_SetFunc(M0P_I2C1, I2cStart_En);   	//启动I2C传输
					SystemStatus=I2CWriteCompleteState;
				}
				break;
			}
			case I2CWriteCompleteState:		//单片机写数据到FRAM,写完成标志状态2
			{
				if(PeriperalStatus.bitField.i2c==0)
				{
					Rxbuff.u8[1]=FRAME_Read;
					I2C_SetFunc(M0P_I2C1, I2cStart_En);   	//启动I2C传输
					PeriperalStatus.bitField.i2c=1;
					SystemStatus = I2CReadCompleteState;
				}
				break;
			}
			case I2CReadCompleteState:		//单片机读FRAM数据,读完成标志状态3
			{
				if(PeriperalStatus.bitField.i2c==0)
				{
					SendData_ToPc();
					SystemStatus = DummyState;
				}
				break;
			}
			default:
              break;
		}
		EnterSleepMode();
	}
}

main.h

#ifndef __MAIN_H__
#define __MAIN_H__

#include "Sys_Init.h"


 /********************************************************************************
 ** \brief 串口待发送类型定义
 ******************************************************************************/
typedef struct 
{
	uint8_t buff[32];	//串口发送数据缓存
	uint8_t I2cbuff[32];	//串口发送数据缓存
	uint8_t XoRbuff[32];	//
	uint8_t idx;	//串口发送数据索引
}TxBuf;

 /********************************************************************************
 ** brief Timer0与IIC外设状态共用体
 ******************************************************************************/
typedef union{
	uint32_t u32;
	struct{
		uint32_t timer0: 	1;
		uint32_t i2c: 	1;
	}bitField;
}PeripheralStatus_t;

/**
 ******************************************************************************
 ** \brief 系统执行过程状态枚举
 *****************************************************************************/
typedef enum SystemStatus
{
	DummyState = 0u,
	RxCompleteState = 1u,
	I2CWriteCompleteState = 2u,
	I2CReadCompleteState = 3u,
}SystemStatus_t;

extern TxBuf TxBuff;
extern SystemStatus_t SystemStatus;
extern PeripheralStatus_t PeriperalStatus;

#endif


Sys_Init.c

/**
 ******************************************************************************
 ** \brief  系统初始化函数
 **
 ** \return 无返回值
 **
 **	时钟初始化,设定为外部低速时钟32768Hz
 ** GPIO初始化
 ** 串口Serial初始化
 ** Timer0初始化 4M
 ** I2C1初始化
 ******************************************************************************/

#include "Sys_Init.h"

/**
 ******************************************************************************
 ** \brief  时钟初始化函数
 **
 ** \return 无返回值
 **
 **	时钟初始化,设定为外部低速时钟32768Hz
 ** 
 ******************************************************************************/

void App_SysClkInit(void)		//时钟初始化,设定为外部低速时钟32768Hz
{
    stc_sysctrl_clk_cfg_t  stcClkCfg;
    
    //时钟初始化
    stcClkCfg.enClkSrc  = SysctrlClkRCH;		
    stcClkCfg.enHClkDiv = SysctrlHclkDiv1;
    stcClkCfg.enPClkDiv = SysctrlPclkDiv1;
    Sysctrl_ClkInit(&stcClkCfg);
    //使能时钟
	Sysctrl_SetRCLTrim(SysctrlRclFreq38400);
	Sysctrl_ClkSourceEnable(SysctrlClkRCL, TRUE);
}

/**
 ******************************************************************************
 ** \brief  异或检验函数
 **
 ** \param 需要校验的数组
 ** \param 检验的数据长度
 **
 ** \return 有返回值(Check),返回校验结果
 **
 ******************************************************************************/

uint8_t XoRCheck(uint8_t *array,uint8_t length)			//数据异或校验
{
	uint8_t i=0 ;
	uint8_t Check = 0; 
	for(i=0; i<length; i++)
	{
		Check ^= array[i];
	}
	return Check;
}

 /********************************************************************************
 ** \brief 系统cpu工作模式切换
 ******************************************************************************/
void EnterSleepMode(void)
{
	if(PeriperalStatus.u32) //如果外设都关闭状态1
	{
		Lpm_GotoSleep(FALSE); // 执行普通睡眠模式
		return;
	}
	Lpm_GotoDeepSleep(FALSE);// 否则,执行深度睡眠模式
}

/**
 ******************************************************************************
 ** \brief  初始化函数
 **
 ** \return 无返回值
 **
 **	各个函数初始化
 ** 
 ******************************************************************************/

void Sys_Init(void)
{	
	App_SysClkInit();		//时钟初始化
	App_Gpio_Init();		//GPIO初始化
	App_Serial_Init();		//Serial初始化
	App_Timer0_Init();		//Timer0初始化 4M
	App_I2c_Init();			//I2C1初始化
}

Sys_Init.h

#ifndef __SYS_INIT_H__
#define __SYS_INIT_H__

#include "App_Gpio_Init.h"
#include "App_Serial_Init.h"
#include "App_Timer0_Init.h"
#include "App_interrupts.h"
#include "App_I2c_Init.h"
#include "ddl.h"

void Sys_Init(void);
uint8_t XoRCheck(uint8_t *array,uint8_t length);
void EnterSleepMode(void);
#endif

App_Gpio_Init.c

/**
 ******************************************************************************
 ** \brief  GPIO初始化函数
 **
 ** \return 无返回值
 **	晶振引脚初始化
 **	I2C引脚初始化,配置复用功能
 ** LPUART1引脚初始化,配置复用功能
 ******************************************************************************/

#include "App_Gpio_Init.h"

volatile uint8_t Flag;

void App_Gpio_Init()
{
	const MCU_IO_TypeDef McuIoInitTbl[]  = 
	{
		{.port  =  GpioPortE, .pin = GpioPin2, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PE02
		{.port  =  GpioPortE, .pin = GpioPin3, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PE03
		{.port  =  GpioPortE, .pin = GpioPin4, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PE04
		{.port  =  GpioPortE, .pin = GpioPin5, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PE05

		{.port  =  GpioPortC, .pin = GpioPin13, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PC13
		{.port  =  GpioPortC, .pin = GpioPin14, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirIn, .io_cfg.enDrv  =  GpioDrvH, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PC14
		{.port  =  GpioPortC, .pin = GpioPin15, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirIn, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PC15

		{.port  =  GpioPortF, .pin = GpioPin0, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PF00
		{.port  =  GpioPortF, .pin = GpioPin1, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirIn, .io_cfg.enDrv  =  GpioDrvH, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PF01->Key
	
		{.port  =  GpioPortC, .pin = GpioPin0, .io_cfg.bOutputVal  =  TRUE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PC00->LED1
		{.port  =  GpioPortC, .pin = GpioPin1, .io_cfg.bOutputVal  =  TRUE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PC01->LED2
		{.port  =  GpioPortC, .pin = GpioPin2, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PC02
		{.port  =  GpioPortC, .pin = GpioPin3, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirIn, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PC03
		
		{.port  =  GpioPortA, .pin = GpioPin0, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PA00
		{.port  =  GpioPortA, .pin = GpioPin1, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PA01
		{.port  =  GpioPortA, .pin = GpioPin2, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PA02->UART1_TXD
		{.port  =  GpioPortA, .pin = GpioPin3, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PA03->UART1_RXD
		
		{.port  =  GpioPortF, .pin = GpioPin4, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PF04
		{.port  =  GpioPortF, .pin = GpioPin5, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PF05
		
		{.port  =  GpioPortA, .pin = GpioPin4, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PA04
		{.port  =  GpioPortA, .pin = GpioPin5, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PA05
		{.port  =  GpioPortA, .pin = GpioPin6, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PA06
		{.port  =  GpioPortA, .pin = GpioPin7, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PA07
		
		{.port  =  GpioPortC, .pin = GpioPin4, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PC04
		{.port  =  GpioPortC, .pin = GpioPin5, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PC05

		{.port  =  GpioPortB, .pin = GpioPin0, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PB00
		{.port  =  GpioPortB, .pin = GpioPin1, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PB01
		{.port  =  GpioPortB, .pin = GpioPin2, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PB02

		{.port  =  GpioPortE, .pin = GpioPin11, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PE11
		{.port  =  GpioPortE, .pin = GpioPin12, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PE12
		{.port  =  GpioPortE, .pin = GpioPin13, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PE13
		{.port  =  GpioPortE, .pin = GpioPin14, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PE14

		{.port  =  GpioPortB, .pin = GpioPin10, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PB10
		{.port  =  GpioPortB, .pin = GpioPin11, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PB11
		{.port  =  GpioPortB, .pin = GpioPin12, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PB12
		{.port  =  GpioPortB, .pin = GpioPin13, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PB13
		{.port  =  GpioPortB, .pin = GpioPin14, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PB14
		{.port  =  GpioPortB, .pin = GpioPin15, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PB15

		{.port  =  GpioPortD, .pin = GpioPin8, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PD08
		{.port  =  GpioPortD, .pin = GpioPin9, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PD09
		
		{.port  =  GpioPortD, .pin = GpioPin10, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PD10
		{.port  =  GpioPortD, .pin = GpioPin11, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PD11
		
		{.port  =  GpioPortC, .pin = GpioPin6, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PC06
		{.port  =  GpioPortC, .pin = GpioPin7, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PC07
		{.port  =  GpioPortC, .pin = GpioPin8, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PC08
		{.port  =  GpioPortC, .pin = GpioPin9, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PC09
		
		{.port  =  GpioPortA, .pin = GpioPin8, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PA08
		{.port  =  GpioPortA, .pin = GpioPin9, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PA09
		{.port  =  GpioPortA, .pin = GpioPin10, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PA10
		{.port  =  GpioPortA, .pin = GpioPin11, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PA11
		{.port  =  GpioPortA, .pin = GpioPin12, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PA12
		//{.port  =  GpioPortA, .pin = GpioPin13, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		//.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PA13->SWDIO
		
		{.port  =  GpioPortF, .pin = GpioPin6, .io_cfg.bOutputVal  =  TRUE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuEnable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdEnable, .io_cfg.enCtrlMode  =  GpioAHB},	//PF06->SCL
		{.port  =  GpioPortF, .pin = GpioPin7, .io_cfg.bOutputVal  =  TRUE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuEnable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdEnable, .io_cfg.enCtrlMode  =  GpioAHB},	//PF07->SCL
	
		//{.port  =  GpioPortA, .pin = GpioPin14, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		//.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PA14->SWCLK
		{.port  =  GpioPortA, .pin = GpioPin15, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PA15->WP
		
		{.port  =  GpioPortC, .pin = GpioPin10, .io_cfg.bOutputVal  =  TRUE , .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuEnable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PC10
		{.port  =  GpioPortC, .pin = GpioPin11, .io_cfg.bOutputVal  =  TRUE, .io_cfg.enDir  =  GpioDirIn, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuEnable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PC11
		{.port  =  GpioPortC, .pin = GpioPin12, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PC12
		
		
		{.port  =  GpioPortD, .pin = GpioPin0, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PD00->SPI1_CS
		{.port  =  GpioPortD, .pin = GpioPin1, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PD01->SPI1_SCK
		{.port  =  GpioPortD, .pin = GpioPin2, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PD02
		{.port  =  GpioPortD, .pin = GpioPin3, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PD03->SPI1_MISO
		{.port  =  GpioPortD, .pin = GpioPin4, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir  =  GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB},	//PD04->SPI1_MOSI
		
		{.port  =  GpioPortB, .pin = GpioPin3, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir = GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB },	//PB03
		{.port  =  GpioPortB, .pin = GpioPin4, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir = GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB },	//PB04
		{.port  =  GpioPortB, .pin  =  GpioPin5, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir = GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB },	//PB05
		{.port  =  GpioPortB, .pin = GpioPin6, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir = GpioDirOut, .io_cfg.enDrv  =  GpioDrvL, 
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB },	//PB06
		{.port  =  GpioPortB, .pin = GpioPin7, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir = GpioDirOut, .io_cfg.enDrv  =  GpioDrvL,
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB },	//PB07
		{.port  =  GpioPortB, .pin = GpioPin8, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir = GpioDirOut, .io_cfg.enDrv  =  GpioDrvL,
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB },	//PB08->UART0_TXD
		{.port  =  GpioPortB, .pin = GpioPin9, .io_cfg.bOutputVal  =  FALSE, .io_cfg.enDir = GpioDirIn, .io_cfg.enDrv  =  GpioDrvL,
		.io_cfg.enPu  =  GpioPuDisable, .io_cfg.enPd  =  GpioPdDisable, .io_cfg.enOD  =  GpioOdDisable, .io_cfg.enCtrlMode  =  GpioAHB }	//PB09->UART0_RXD
	};

	Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
	
	for(uint16_t i = 0; i<ARRAY_SZ(McuIoInitTbl); i++)
	{
		Gpio_Init(McuIoInitTbl[i].port, McuIoInitTbl[i].pin, (stc_gpio_cfg_t  *)&McuIoInitTbl[i].io_cfg);
	}
    Gpio_SetAfMode(GpioPortC,GpioPin10,GpioAf1); 			//配置PC10为LPUART1_TX
    Gpio_SetAfMode(GpioPortC,GpioPin11,GpioAf1); 			//配置PC11为LPUART1_RX
	Gpio_SetAfMode(GpioPortF, GpioPin6,GpioAf1);           ///< 配置PF06为SCL
    Gpio_SetAfMode(GpioPortF, GpioPin7,GpioAf1);           ///< 配置PF07为SDA
}


App_Gpio_Init.h

#ifndef __APP_GPIO_INIT_H__
#define __APP_GPIO_INIT_H__

#include "gpio.h"
#include "ddl.h"
#include "sysctrl.h"

 /********************************************************************************
 ** \brief GPIO外设初始化结构体
 ******************************************************************************/
typedef struct{
	en_gpio_port_t port;		// GPIO端口号
	en_gpio_pin_t  pin; 		// GPIO引脚号
	stc_gpio_cfg_t io_cfg; 		// GPIO配置信息
}MCU_IO_TypeDef;

void App_Gpio_Init(void);

#endif

App_Serial_Init.c

/**
 ******************************************************************************
 ** \brief  Serial串口初始化函数
 **
 ** \return 无返回值
 **	
 **	采用LpUart1,内部低速时钟,38400,波特率为9600,异步全双工工作模式
 ** 
 ******************************************************************************/

#include "App_Serial_Init.h"


void App_Serial_Init(void)
{
	stc_lpuart_cfg_t  stcCfg;

    DDL_ZERO_STRUCT(stcCfg);
    
    ///<外设模块时钟使能
    Sysctrl_SetPeripheralGate(SysctrlPeripheralLpUart1,TRUE);    
    
    ///<LPUART 初始化
    stcCfg.enStopBit = LPUart1bit;                   ///<1停止位    
    stcCfg.enMmdorCk = LPUartOdd;                   ///<奇校验
    stcCfg.stcBaud.enSclkSel = LPUartMskRcl;        ///<传输时钟源
    stcCfg.stcBaud.u32Sclk = 38400; 				///<PCLK获取
    stcCfg.stcBaud.enSclkDiv = LPUartMsk4Or8Div;     ///<采样分频
    stcCfg.stcBaud.u32Baud = 9600;                   ///<波特率
    stcCfg.enRunMode = LPUartMskMode3;               ///<工作模式
    LPUart_Init(M0P_LPUART1, &stcCfg);
  ///<LPUART 中断使能
    LPUart_ClrStatus(M0P_LPUART1,LPUartRC);          ///<清接收中断请求
    LPUart_ClrStatus(M0P_LPUART1,LPUartTC);          ///<清发送中断请求
    LPUart_EnableIrq(M0P_LPUART1,LPUartRxIrq);      ///<使能接收中断
    LPUart_EnableIrq(M0P_LPUART1,LPUartTxIrq);       ///<使能发送中断
    EnableNvic(LPUART1_IRQn,IrqLevel3,TRUE);         ///<系统中断使能
}

App_Serial_Init.h

#ifndef __APP_SERIAL_INIT_H__
#define __APP_SERIAL_INIT_H__

#include "lpuart.h"
#include "gpio.h"
#include "sysctrl.h"

extern void App_Serial_Init(void);

#endif

App_interrupts.c

/**
 ******************************************************************************
 ** \brief  中断函数的集合(低功耗串口,I2C中断,定时器Timer0中断)
 **
 ** \return 无返回值
 **
 ******************************************************************************/

#include "App_interrupts.h"

RxBuf Rxbuff;								//定义结构体类型变量
volatile uint8_t State = 0;					//获取状态机变量(电脑接收数据完成状态1,I2C写完成状态2,I2C读完成状态3)
volatile uint8_t Comm_flg  = 0;				//判断读写标志
volatile uint8_t u8SendLen = 0;				//发送数组长度
volatile uint8_t u8ReadLen   =10;			//读取数组长度
volatile uint8_t Rxbuff01;					//读取数组长度
volatile uint8_t Command_bit;
//static boolean_t Flag=0;					//翻转电平控制变量

/**
 ******************************************************************************
 ** \brief  LPUART1 中断服务函数
 **
 ** \return 无返回值
 **	
 ******************************************************************************/

///<LPUART1 中断服务函数
void LpUart1_IRQHandler(void)
{	
    if(LPUart_GetStatus(M0P_LPUART1, LPUartTC))		///发送数据
    {
		LPUart_ClrStatus(M0P_LPUART1, LPUartTC);   	///<清发送中断请求
		LpUart_Send();
    }
    if(LPUart_GetStatus(M0P_LPUART1, LPUartRC))    ///接收数据
    {
		LPUart_ClrStatus(M0P_LPUART1, LPUartRC);   ///<清接收中断请求
		Rxbuff.u8[Rxbuff.idx] = LPUart_ReceiveData(M0P_LPUART1);///读取数据
		Rxbuff.idx = (Rxbuff.idx > sizeof(Rxbuff.u8)? Rxbuff.idx:(Rxbuff.idx+1));
		Bt_M0_Cnt16Set(TIM0,60736);	//重载值,1s/4M=1*10^6 / 4*1*10^6 =0.25us  1.2ms/0.25us = 4800  65536-4800=60736
		Bt_M0_Run(TIM0);
		PeriperalStatus.bitField.timer0 = 1;
	}
}

/**
 ******************************************************************************
 ** \brief  Tim0中断服务函数
 **
 ** \return 无返回值
 **
 ******************************************************************************/

//Tim0中断服务函数
void Tim0_IRQHandler(void)
{
	Bt_ClearIntFlag(TIM0,BtUevIrq);			//中断清除
	Bt_M0_Stop(TIM0);						//停止timer0
	Rxbuff01= Rxbuff.u8[1];
	Rxbuff.len= Rxbuff.idx;					//串口数组长度
	Rxbuff.idx=0;							//串口接受数据索引清0
	Rxbuff.idt=0;							//串口发送数据索引清0
	Rxbuff.idc=2;							//I2C读取数据索初始化为2(前两位为起始位和读成功校验位)
	PeriperalStatus.bitField.timer0=0;
	SystemStatus= RxCompleteState;								//状态标志位,接收完成
}

/**
 ******************************************************************************
 ** \brief  I2c1中断服务函数
 **
 ** \return 无返回值
 **	
 **
 ******************************************************************************/

///< I2c1中断函数
void I2c1_IRQHandler(void)
{
	Command_bit=Rxbuff.u8[1];
	
	switch(Command_bit)
	{
		case FRAME_Write:      //I2C写                    
		{
			I2C_PageWrite(Rxbuff.u8);
            break;
		}
		case FRAME_Read:    //I2C读
		{
			I2C_PageRead(Rxbuff.I2);
			break;
		}
	}
}


App_interrupts.h

#ifndef __APP_INTERRUPTS_H__
#define __APP_INTERRUPTS_H__

#include "Sys_Init.h"
#include "main.h"
#include "Data_treating.h"

 /********************************************************************************
 ** \brief 串口接收数据类型定义
 ******************************************************************************/
typedef struct 
{
	uint8_t u8[32];		//串口接收数据缓存
	uint8_t I2[32];		//I2C接收数据缓存
	uint8_t idx;		//串口接收数据索引
	uint8_t idt;		//串口发送数据索引
	uint8_t idc;		//I2C数据索引
	uint8_t len;		//串口接收数据长度缓存
}RxBuf;

extern volatile uint8_t State;
extern RxBuf Rxbuff;
extern volatile uint8_t Rxbuff01;
extern volatile uint8_t Command_bit;
#endif


App_Timer0_Init.c

/**
 ******************************************************************************
 ** \brief  Timer0定时器初始化函数
 **
 ** \return 无返回值
 **	
 **	采用Timer0,定时器模式,采用内部4M时钟,初值设置为60736,计时1.2ms溢出,触发中断
 ** 
 ******************************************************************************/

#include "App_Timer0_Init.h"


void App_Timer0_Init()
{
	stc_bt_mode0_cfg_t stcBtConfig;
	DDL_ZERO_STRUCT(stcBtConfig);
	Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, TRUE);
	
	stcBtConfig.enWorkMode = BtWorkMode0;
	stcBtConfig.bEnGate = FALSE;
	stcBtConfig.enPRS = BtPCLKDiv1;
	stcBtConfig.bEnTog = FALSE;
	stcBtConfig.enCT = BtTimer;
	stcBtConfig.enCntMode = Bt16bitArrMode;
	Bt_Mode0_Init(TIM0, &stcBtConfig);
	Bt_M0_ARRSet(TIM0,60736);				//重载值,1s/4M=1*10^6 / 4*1*10^6 =0.25us  1.2ms/0.25us = 4800  65536-4800=60736
	
	Bt_ClearIntFlag(TIM0,BtUevIrq);			//中断清除
	Bt_Mode0_EnableIrq(TIM0);				//中断使能
	EnableNvic(TIM0_IRQn,IrqLevel3,TRUE);			//NVIC使能
}


App_Timer0_Init.h

#ifndef __APP_TIMER0_INIT_H__
#define __APP_TIMER0_INIT_H__

#include "bt.h"
#include "ddl.h"
#include "lpm.h"
#include "clk.h"
#include "gpio.h"

extern void App_Timer0_Init(void);

#endif

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值