stm32_ota/SYSTEM/IO/io.c

286 lines
13 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "io.h"
#include <math.h>
#include "stm32f10x_exti.h"
#include "usart.h"
/********************************************************************************
* @file io.c
* @author 晏诚科技 Mr.Wang
* @version V1.0.0
* @date 11-Dec-2018
* @brief 提供IO 外部中断相关驱动
******************************************************************************
* @驱动功能:
* 1、GPIO初始化
* 2、IOEXTI初始化
* 3、外部中断回调函数注册函数
* 4、GPIO输出电平翻转
* 5、本驱动没有实现输出IO电平在上册应用中直接使用位带操作更改输出高低电平
* @使用方法:
* 1、先调用IoExti_Init()对IO初始化、NVIC、EXTI初始化
* 2、在上层注册回调函数编写回调函数
*******************************************************************************/
/*****************************************
*中断事件回调函数相关配置
****************************************/
IOFP ioFp[PINSUM] = {NULL} ; //EXTI_Line0~EXTI_Line15 定义16个IO中断线对应的回调函数指针
/****************************************************************************
* IO EXTI相关配置
****************************************************************************/
const uint32_t portRcc[PSUM] = {RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB, RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD,
RCC_APB2Periph_GPIOE, RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG} ; //所有IO端口的时钟
GPIO_TypeDef* portx[PSUM] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG} ; //所有IO端口
const uint16_t pinx[PINSUM] = {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_Pin_8, GPIO_Pin_9, GPIO_Pin_10, GPIO_Pin_11,
GPIO_Pin_12,GPIO_Pin_13, GPIO_Pin_14, GPIO_Pin_15} ; //IO端口下的所有IO引脚
const uint8_t extiPort[PSUM] = {GPIO_PortSourceGPIOA, GPIO_PortSourceGPIOB, GPIO_PortSourceGPIOC,
GPIO_PortSourceGPIOD, GPIO_PortSourceGPIOE, GPIO_PortSourceGPIOF,
GPIO_PortSourceGPIOG} ; //所有中断端口
const uint8_t extiPin[PINSUM] = {GPIO_PinSource0, GPIO_PinSource1, GPIO_PinSource2, GPIO_PinSource3,
GPIO_PinSource4, GPIO_PinSource5, GPIO_PinSource6, GPIO_PinSource7,
GPIO_PinSource8, GPIO_PinSource9, GPIO_PinSource10, GPIO_PinSource11,
GPIO_PinSource12, GPIO_PinSource13, GPIO_PinSource14, GPIO_PinSource15,} ; //所有IO外部中断引脚
const uint32_t extiLine[PINSUM] = {EXTI_Line0, EXTI_Line1, EXTI_Line2, EXTI_Line3,
EXTI_Line4, EXTI_Line5, EXTI_Line6, EXTI_Line7,
EXTI_Line8, EXTI_Line9, EXTI_Line10, EXTI_Line11,
EXTI_Line12, EXTI_Line13, EXTI_Line14, EXTI_Line15} ; //所有外部中断线
const uint8_t extiChannel[PINSUM] = {EXTI0_IRQn, EXTI1_IRQn, EXTI2_IRQn, EXTI3_IRQn,
EXTI4_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn,
EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn,
EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, } ; //所有中断通道
/**************************************************************************************************
* 名 称void Gpio_Init(PORT_e ePortx, PIN_e ePinx, GPIOMode_TypeDef gpioMode)
* 功能说明GPIO初始化
* 入口参数:
* @param1 ePortx PORT_e枚举类型表示IO端口
* @param2 ePinx PIN_e枚举类型数据表示IO引脚
* @param3 gpioMode GPIOMode_TypeDef枚举类型表示IO引脚模式
* 出口参数:无
* 调用方法:外部调用
*************************************************************************************************/
void Gpio_Init(PORT_e ePortx, PIN_e ePinx, GPIOMode_TypeDef gpioMode)
{
/*通用IO引脚初始化*/
GPIO_InitTypeDef GPIO_InitStructure ; //GPIO参数 结构体定义
RCC_APB2PeriphClockCmd(portRcc[ePortx] , ENABLE); //GPIO 端口时钟开启
GPIO_InitStructure.GPIO_Pin = pinx[ePinx] ; //需要初始化引脚
GPIO_InitStructure.GPIO_Mode = gpioMode ; //IO引脚模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO速度配置
GPIO_Init(portx[ePortx], &GPIO_InitStructure); //GPIO 引脚初始化
}
/**************************************************************************************************
* 名 称void IoExti_Init(PORT_e ePortx, PIN_e ePinx, GPIOMode_TypeDef gpioMode, EXTITrigger_TypeDef exitTrigger,
* IntPriority_e ePriority, IOFP pCallback)
* 功能说明io初始化。GPIO初始化判断如果gpioMode开启了外部中断则初始化EXTI和NVIC接着注册中断回调函数
* 入口参数:
* @param1 ePortx PORT_e枚举类型表示IO端口
* @param2 ePinx PIN_e枚举类型数据表示IO引脚
* @param3 gpioMode GPIOMode_TypeDef枚举类型表示IO引脚模式
* @param4 exitTrigger EXTITrigger_TypeDef枚举类型数据表示IO中断触发模式
* @param5 ePriority IntPriority_e枚举类型表示IO端口中断抢占优先级
* @param6 pCallback IOFP类型函数指针
* 出口参数:无
* 调用方法:外部调用
*************************************************************************************************/
void IoExti_Init(PORT_e ePortx, PIN_e ePinx, GPIOMode_TypeDef gpioMode, EXTITrigger_TypeDef exitTrigger,
IntPriority_e ePriority)
{
Gpio_Init(ePortx, ePinx, gpioMode) ; //通用IO引脚初始化
if((GPIO_Mode_IPD==gpioMode) || (GPIO_Mode_IPU==gpioMode)) //判断是否开启了IO外部中断
{
/*开启EXIT功能需要 开启AFIO时钟且初始化 EXIT和NVIC*/
EXTI_InitTypeDef EXTI_InitStructure ; //EXIT参数 结构体定义
NVIC_InitTypeDef NVIC_InitStructure ; //NVIC参数 结构体定义
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //GPIO EXIT功能需要开启AFIO时钟
NVIC_InitStructure.NVIC_IRQChannel = extiChannel[ePinx] ; //外部中断线
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ePriority ; //抢占优先级配置
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0 ; //freertos无子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE ; //失能外部中断通道
NVIC_Init(&NVIC_InitStructure); //中断NVIC配置
GPIO_EXTILineConfig( extiPort[ePortx], extiPin[ePinx] ) ; //中断Line配置
EXTI_InitStructure.EXTI_Line = extiLine[ePinx] ; //中断引脚
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt ; //中断模式
EXTI_InitStructure.EXTI_Trigger = exitTrigger ; //IO外部中断触发方式
EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能外部中断
EXTI_Init( &EXTI_InitStructure ); //外部中断初始化
/*清中断标志位后再开中断*/
EXTI_ClearITPendingBit( extiLine[ePinx] );
NVIC_EnableIRQ(extiChannel[ePinx]) ;
}
}
/**************************************************************************************************
* 名 称void Io_Reverse(PORT_e ePortx, PIN_e ePinx)
* 功能说明GPIO输出电平翻转
* 入口参数:
* @param1 ePortx PORT_e枚举类型表示IO端口
* @param2 ePinx PIN_e枚举类型数据表示IO引脚
* 调用方法:外部调用
*************************************************************************************************/
void Io_Reverse(PORT_e ePortx, PIN_e ePinx)
{
portx[ePortx]->ODR ^= pinx[ePinx] ;
}
/**************************************************************************************************
* 名 称IOFP Io_RegHookCallback(PIN_e ePinx, IOFP pCallback)
* 功能说明io外部中断回调函数-注册函数EXTI驱动中定义了IOFP函数指针类型并定义了ioFp16个中断指针变量
* Io_RegHookCallback函数就是将回调函数地址传递给ioFp指针变量
* 入口参数:
* @param1 ePinx PIN_e枚举类型数据
* @param2 pCallback IOFP类型函数指针
* 出口参数:
* @param1 pCallback IOFP类型函数指针
* 调用方法:外部调用
*************************************************************************************************/
IOFP Io_RegHookCallback(PIN_e ePinx, IOFP pCallback)
{
if( ioFp[ePinx] == NULL )
ioFp[ePinx] = pCallback ;
else
SysErr("IO Callback repeat reg!") ;
return pCallback ;
}
/**************************************************************************************************
* 名 称void Io_Hook(uint32_t extiLine)
* 功能说明io外部中断内调用的钩子函数执行到中断会把相应的回调函数勾出来运行嘿嘿嘿。。。
* 当然不同的中断线extiLine会勾出不同的回调函数ioFp[]
* 入口参数:
* @param1 extiLine 中断线EXTI_Line0~EXTI_Line15
*************************************************************************************************/
void Io_Hook(uint32_t extiLine)
{
int n = log(extiLine)/log(2) ; //对数运算将extiLine的值转化为中断线需要0~15
if( ioFp[n] != NULL)
ioFp[n]() ; //通过ipFP函数指针跳转到已经注册的回调函数运行
}
/**************************************************************************************************
* 名 称: void EXTI0_IRQHandler(void)
* 功能说明: EXTI0_IRQn中断处理函数
*************************************************************************************************/
void EXTI0_IRQHandler(void)
{
if( EXTI_GetFlagStatus(EXTI_Line0) != RESET )
{
EXTI_ClearFlag( EXTI_Line0 ); //清除LINE0上的中断标志位
SysLog("EXTI0 IRQ!") ;
Io_Hook(EXTI_Line0) ; //跳转到EXTI0中断回调函数运行
}
EXTI_ClearITPendingBit( EXTI_Line0 ); //清除LINE0上的中断标志位
}
/**************************************************************************************************
* 名 称: void EXTI1_IRQHandler(void)
* 功能说明: EXTI1_IRQn中断处理函数
*************************************************************************************************/
void EXTI1_IRQHandler(void)
{
if( EXTI_GetFlagStatus( EXTI_Line1 ) == SET )
{
EXTI_ClearFlag( EXTI_Line1 );
SysLog("EXTI1 IRQ!") ;
Io_Hook(EXTI_Line1) ; //EXTI1中断回调函数
}
EXTI_ClearITPendingBit( EXTI_Line1 ); //清除LINE1上的中断标志位
}
/**************************************************************************************************
* 名 称: void EXTI2_IRQHandler(void)
* 功能说明: EXTI2_IRQn中断处理函数
*************************************************************************************************/
void EXTI2_IRQHandler(void)
{
if( EXTI_GetFlagStatus(EXTI_Line2) != RESET )
{
EXTI_ClearFlag( EXTI_Line2 ); //清除LINE2上的中断标志位
SysLog("EXTI2 IRQ!") ;
Io_Hook(EXTI_Line2) ; //EXTI2中断回调函数
}
EXTI_ClearITPendingBit( EXTI_Line2 ); //清除LINE2上的中断标志位
}
/**************************************************************************************************
* 名 称: void EXTI3_IRQHandler(void)
* 功能说明: EXTI3_IRQn中断处理函数
*************************************************************************************************/
void EXTI3_IRQHandler(void)
{
if( EXTI_GetFlagStatus( EXTI_Line3 ) == SET )
{
EXTI_ClearFlag( EXTI_Line3 );
SysLog("EXTI3 IRQ!") ;
Io_Hook(EXTI_Line3) ; //EXTI3中断回调函数
}
EXTI_ClearITPendingBit( EXTI_Line3 ); //清除LINE3上的中断标志位
}
/**************************************************************************************************
* 名 称: void EXTI4_IRQHandler(void)
* 功能说明: EXTI4_IRQn中断处理函数
*************************************************************************************************/
void EXTI4_IRQHandler(void)
{
if( EXTI_GetFlagStatus(EXTI_Line4) != RESET )
{
EXTI_ClearFlag( EXTI_Line4 ); //清除LINE4上的中断标志位
SysLog("EXTI4 IRQ!") ;
Io_Hook(EXTI_Line4) ; //EXTI4中断回调函数
}
EXTI_ClearITPendingBit( EXTI_Line4 ); //清除LINE4上的中断标志位
}
/**************************************************************************************************
* 名 称: void EXTI9_5_IRQHandler(void)
* 功能说明: EXTI_Line5~EXTI_Line9中断处理函数
*************************************************************************************************/
void EXTI9_5_IRQHandler(void)
{
for( int n=5; n<=9; n++ )
{
if( EXTI_GetITStatus(extiLine[n]) != RESET )
{
EXTI_ClearFlag( extiLine[n] ); //清除EXTI9_5上的中断标志位
char log[64] = {0} ;
snprintf(log, 64, "EXTI%d IRQ!", n) ;
SysLog(log) ;
Io_Hook(extiLine[n]) ; //EXTI9_5中断回调函数
}
}
}
/**************************************************************************************************
* 名 称: void EXTI15_10_IRQHandler(void)
* 功能说明: EXTI_Line15~EXTI_Line10中断处理函数
*************************************************************************************************/
void EXTI15_10_IRQHandler(void)
{
for( int n=10; n<=15; n++ )
{
if( EXTI_GetITStatus(extiLine[n]) != RESET )
{
EXTI_ClearFlag( extiLine[n] ); //清除EXTI15_10上的中断标志位
char log[64] = {0} ;
snprintf(log, 64, "EXTI%d IRQ!", n) ;
SysLog(log) ;
Io_Hook(extiLine[n]) ; //EXTI15_10中断回调函数
}
}
}