SmartOS/Port.cpp

278 lines
7.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "Port.h"
#ifdef STM32F10X
#include "stm32f10x_exti.h"
#else
#include "stm32f0xx_exti.h"
#endif
#ifndef BIT
#define BIT(x) (1 << (x))
#endif
/* 中断状态结构体 */
/* 一共16条中断线意味着同一条线每一组只能有一个引脚使用中断 */
typedef struct TIntState
{
Pin Pin;
IOReadHandler Handler;
bool OldValue;
} IntState;
/*默认按键去抖延时 70ms*/
static byte shake_time=70;
// 16条中断线
static IntState State[16];
#ifdef STM32F0XX
#define _RCC_AHB(PIN) (RCC_AHBENR_GPIOAEN << (PIN >> 4))
void OpenClock(Pin pin)
{
// 打开时钟
RCC_APB2PeriphClockCmd(_RCC_APB2(pin), ENABLE);
}
#else
#define _RCC_APB2(PIN) (RCC_APB2Periph_GPIOA << (PIN >> 4))
void OpenClock(Pin pin)
{
// 打开时钟
RCC_APB2PeriphClockCmd(_RCC_APB2(pin), ENABLE);
}
#endif
// 打开端口
// mode=GPIO_Mode_IN/GPIO_Mode_OUT/GPIO_Mode_AF/GPIO_Mode_AN
// speed=GPIO_Speed_50MHz/GPIO_Speed_2MHz/GPIO_Speed_10MHz
// type=GPIO_OType_PP/GPIO_OType_OD
// PuPd= GPIO_PuPd_NOPULL/ GPIO_PuPd_UP /GPIO_PuPd_DOWN
void Port::Set(Pin pin, Port::Mode_TypeDef mode, bool isOD, Port::Speed_TypeDef speed, Port::PuPd_TypeDef pupd)
{
GPIO_InitTypeDef p;
// 初始化结构体,保险起见。为了节省代码空间,也可以不用
GPIO_StructInit(&p);
// 打开时钟
OpenClock(pin);
p.GPIO_Pin = _PORT(pin);
p.GPIO_Speed = (GPIOSpeed_TypeDef)speed;
#ifdef STM32F0XX
p.GPIO_Mode = mode;
p.GPIO_OType = isOD ? GPIO_OType_OD : GPIO_OType_PP;
#else
switch(mode)
{
case Port::Mode_IN:
p.GPIO_Mode = isOD ? GPIO_Mode_AIN : GPIO_Mode_IN_FLOATING;
break;
case Port::Mode_OUT:
p.GPIO_Mode = isOD ? GPIO_Mode_Out_OD : GPIO_Mode_Out_PP;
break;
case Port::Mode_AF:
p.GPIO_Mode = isOD ? GPIO_Mode_AF_OD : GPIO_Mode_AF_PP;
break;
case Port::Mode_AN:
p.GPIO_Mode = isOD ? GPIO_Mode_IPD : GPIO_Mode_IPU;
break;
}
#endif
GPIO_Init(_GROUP(pin), &p);
}
void Port::SetInput(Pin pin, bool isFloating, Port::Speed_TypeDef speed)
{
Set(pin, Port::Mode_IN, !isFloating, speed);
}
void Port::SetOutput(Pin pin, bool isOD, Port::Speed_TypeDef speed)
{
Set(pin, Port::Mode_OUT, isOD, speed);
}
void Port::SetAlternate(Pin pin, bool isOD, Port::Speed_TypeDef speed)
{
Set(pin, Port::Mode_AF, isOD, speed);
}
void Port::SetAnalog(Pin pin, bool isOD, Port::Speed_TypeDef speed)
{
Set(pin, Port::Mode_AN, isOD, speed);
}
// 设置端口状态
void Port::Write(Pin pin, bool value)
{
if(value)
GPIO_SetBits(_GROUP(pin), _PORT(pin));
else
GPIO_ResetBits(_GROUP(pin), _PORT(pin));
}
// 读取端口状态
bool Port::Read(Pin pin)
{
GPIO_TypeDef* group = _GROUP(pin);
return (group->IDR >> (pin & 0xF)) & 1;
}
// 注册回调 及中断使能
void Port::Register(Pin pin, IOReadHandler handler)
{
//byte port = _PORT(pin);
byte pins = pin & 0x0F;
IntState* state = &State[pins];
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 注册中断事件
if(handler)
{
// 检查是否已经注册到别的引脚上
if(state->Pin != pin && state->Pin != P0)
{
#if DEBUG
printf("EXTI%d can't register to P%c%d, it has register to P%c%d\r\n", pins, _PIN_NAME(pin), _PIN_NAME(state->Pin));
#endif
return;
}
state->Pin = pin;
state->Handler = handler;
/* 打开时钟 */
#ifdef STM32F0XX
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
SYSCFG_EXTILineConfig(pin>>4, pins);
#else
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_EXTILineConfig(pin>>4, pins);
#endif
/* Configure EXTI0 line */
//EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Line = EXTI_Line0 << pins;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/* Enable and set EXTI0 Interrupt to the lowest priority */
#ifdef STM32F10X
//NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
if(pins < 5)
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn + 6;
else if(pins < 10)
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
else
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0xff;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0xff;
#else
if(pins<0x02)
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_1_IRQn;
if(pins<0x04)
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_3_IRQn;
else
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_15_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0x01; //为滴答定时器让道 中断优先级不为最高
#endif
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
else
{
// 取消注册
state->Pin = P0;
state->Handler = 0;
}
}
//.............................中断函数处理部分.............................
#define IT 1
#ifdef IT
void GPIO_ISR (int num) // 0 <= num <= 15
{
IntState* state = &State[num];
uint bit = 1 << num;
bool value;
//byte line = EXTI_Line0 << num;
// 如果未指定委托,则不处理
if(!state->Handler) return;
//if(EXTI_GetITStatus(line) == RESET) return;
do {
//value = TIO_Read(state->Pin); // 获取引脚状态
EXTI->PR = bit; // 重置挂起位
value = Port::Read(state->Pin); // 获取引脚状态
Sys.Sleep(shake_time); // 避免抖动 在os_cfg.h里面修改
} while (EXTI->PR & bit); // 如果再次挂起则重复
//EXTI_ClearITPendingBit(line);
if(state->Handler)
{
state->Handler(state->Pin, value);
}
}
#ifdef STM32F10X
void EXTI0_IRQHandler (void) { GPIO_ISR(0); } // EXTI0
void EXTI1_IRQHandler (void) { GPIO_ISR(1); } // EXTI1
void EXTI2_IRQHandler (void) { GPIO_ISR(2); } // EXTI2
void EXTI3_IRQHandler (void) { GPIO_ISR(3); } // EXTI3
void EXTI4_IRQHandler (void) { GPIO_ISR(4); } // EXTI4
void EXTI9_5_IRQHandler (void) // EXTI5 - EXTI9
{
uint pending = EXTI->PR & EXTI->IMR & 0x03E0; // pending bits 5..9
int num = 5; pending >>= 5;
do {
if (pending & 1) GPIO_ISR(num);
num++; pending >>= 1;
} while (pending);
}
void EXTI15_10_IRQHandler (void) // EXTI10 - EXTI15
{
uint pending = EXTI->PR & EXTI->IMR & 0xFC00; // pending bits 10..15
int num = 10; pending >>= 10;
do {
if (pending & 1) GPIO_ISR(num);
num++; pending >>= 1;
} while (pending);
}
#else
//stm32f0xx
void EXTI0_1_IRQHandler(void)
{
uint pending = EXTI->PR & EXTI->IMR & 0x0003; // pending bits 0..1
int num = 0; pending >>= 0;
do {
if (pending & 1) GPIO_ISR(num);
num++; pending >>= 1;
} while (pending);
}
void EXTI2_3_IRQHandler(void)
{
uint pending = EXTI->PR & EXTI->IMR & 0x000c; // pending bits 3..2
int num = 2; pending >>= 2;
do {
if (pending & 1) GPIO_ISR(num);
num++; pending >>= 1;
} while (pending);
}
void EXTI4_15_IRQHandler(void)
{
uint pending = EXTI->PR & EXTI->IMR & 0xFFF0; // pending bits 4..15
int num = 4; pending >>= 4;
do {
if (pending & 1) GPIO_ISR(num);
num++; pending >>= 1;
} while (pending);
}
#endif //STM32F10X
#endif //IT
void Port::SetShakeTime(byte ms)
{
shake_time = ms;
}