
칩에서 우리가 하드웨어 적으로 bitwise 연산 해줄게 -> 이게 무슨 뜻인지 읽어보자

여기서 OTYPER에 0x01 써서 open drain 줬더니 그냥 코드가 죽어버렸다. ㅜㅜ
//Structure & Array
typedef struct
{
volatile unsigned int MODER; /*!< GPIO port mode register, Address offset: 0x00 */
volatile unsigned int OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */
volatile unsigned int OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */
volatile unsigned int PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */
volatile unsigned int IDR; /*!< GPIO port input data register, Address offset: 0x10 */
volatile unsigned int ODR; /*!< GPIO port output data register, Address offset: 0x14 */
volatile unsigned int BSRR; /*!< GPIO port bit set/reset registerBSRR, Address offset: 0x18 */
volatile unsigned int LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */
volatile unsigned int AFR[2]; /*!< GPIO alternate function register, Address offset: 0x20-0x24 */
volatile unsigned int BRR; /*!< GPIO bit reset register, Address offset: 0x28 */
}GPIO_TypeDef;
#define PERIPH_BASE (0x40000000UL) /*!< Peripheral base address in the alias region */
#define AHBPERIPH_BASE (PERIPH_BASE + 0x00020000UL)
#define RCC_BASE (AHBPERIPH_BASE + 0x00001000UL)
#define RCC_IOPENR *((volatile unsigned int*)(RCC_BASE + 0x0000002CUL))
#define RCC_GPIOA_EN ((unsigned int)0x00000001U)
//#define GPIO_PA5PIN_BASE (unsigned int)0x50000000UL
#define GPIOA_BASE ((unsigned int)0x50000000UL)
#define GPIOA (GPIO_TypeDef *) GPIOA_BASE
#define GPIO_PIN_5_POS 5
#define GPIO_2BIT_POS_MASK ((unsigned int)0x00000003U)
#define GPIO_1BIT_POS_MASK ((unsigned int)0x00000001U)
#define GPIO_MODE_OUTPUT ((unsigned int)0x00000001U) /*!< GPIO OutPut Mode */
#define GPIO_OUTPUT_TYPE_0 ((unsigned int)0x00000000U) /* PushPull */
#define GPIO_NOPUPD ((unsigned int)0x00000000U) /* No Pull up / down */
#define GPIO_SPEED_FREQ_VERY_HIGH ((unsigned int)0x00000003U) /*!< range 10 MHz to 35 MHz, please refer to the product datasheet */
#define LED2_ON ((unsigned int)0x00000001U)
#define LED2_OFF ((unsigned int)0x00000000U)
void delay(unsigned int delay_cnt)
{
volatile int counter = 0;
while(counter < delay_cnt) //delay loop
{
counter++;
}
}
int main()
{
unsigned int position = GPIO_PIN_5_POS; //Pin Position: PA5
unsigned int temp = 0x0U;
unsigned int mode = 0x0U;
unsigned int reg = 0x0U;
GPIO_TypeDef *GPIOA_reg = GPIOA;
//RCC-GPIOA
RCC_IOPENR |= RCC_GPIOA_EN;
//PA5 Mode
reg = GPIOA_reg->MODER; //GPIO_PA5PIN_MODE
temp = ~(GPIO_2BIT_POS_MASK << (position*2U)); //0xFFFFF3FF
reg &= temp;
mode = GPIO_MODE_OUTPUT << (position*2U) ; // GPO Mode - 2bit 0x00000400
reg |= mode;
GPIOA_reg->MODER = reg;
//OTYPER
reg = GPIOA_reg->OTYPER; //GPIO_PA5PIN_OTYPE
temp = ~(GPIO_1BIT_POS_MASK << position); //~0x20 ==> 0xFFFFFFDF
reg &= temp;
mode = GPIO_OUTPUT_TYPE_0 << position ; //PP Output type - 1bit
reg |= mode;
GPIOA_reg->OTYPER = reg;
//OSPEEDR
reg = GPIOA_reg->OSPEEDR; //GPIO_PA5PIN_OSPEEDR
temp = ~(GPIO_2BIT_POS_MASK << (position*2U)); //0xFFFFF3FF
reg &= temp;
mode = GPIO_SPEED_FREQ_VERY_HIGH << (position*2U) ; //Very High Mode - 2bit 0x00000C00
reg |= mode;
GPIOA_reg->OSPEEDR = reg;
//OPUPDR
reg = GPIOA_reg->PUPDR;
temp = ~(0x03U << (position*2U)); //0xFFFFF3FF
reg &= temp;
mode = 0x0U << (position*2U) ; //No Pull Up - Pull Down - 2bit 0x24000000
reg |= mode;
GPIOA_reg->PUPDR = reg;
//ODR
reg = GPIOA_reg->ODR; //GPIO_PA5PIN_ODR
temp = ~(GPIO_1BIT_POS_MASK << position); //~0x20 ==> 0xFFFFFFDF
reg &= temp;
mode = LED2_ON << position ;
GPIOA_reg->ODR = reg | mode;
while(1)
{
delay(0x20000);
mode = ~mode&(GPIO_1BIT_POS_MASK << position);
GPIOA_reg->ODR = reg | mode;
}
}
이 코드를 이제 함수화 시켜보자
//Structure & Array
typedef struct
{
volatile unsigned int MODER; /*!< GPIO port mode register, Address offset: 0x00 */
volatile unsigned int OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */
volatile unsigned int OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */
volatile unsigned int PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */
volatile unsigned int IDR; /*!< GPIO port input data register, Address offset: 0x10 */
volatile unsigned int ODR; /*!< GPIO port output data register, Address offset: 0x14 */
volatile unsigned int BSRR; /*!< GPIO port bit set/reset registerBSRR, Address offset: 0x18 */
volatile unsigned int LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */
volatile unsigned int AFR[2]; /*!< GPIO alternate function register, Address offset: 0x20-0x24 */
volatile unsigned int BRR; /*!< GPIO bit reset register, Address offset: 0x28 */
}GPIO_TypeDef;
typedef enum
{
GPIO_PIN_RESET = 0U,
GPIO_PIN_SET
} GPIO_PinState;
#define PERIPH_BASE (0x40000000UL) /*!< Peripheral base address in the alias region */
#define AHBPERIPH_BASE (PERIPH_BASE + 0x00020000UL)
#define RCC_BASE (AHBPERIPH_BASE + 0x00001000UL)
#define RCC_IOPENR *((volatile unsigned int*)(RCC_BASE + 0x0000002CUL))
#define RCC_GPIOA_EN ((unsigned int)0x00000001U)
//#define GPIO_PA5PIN_BASE (unsigned int)0x50000000UL
#define GPIOA_BASE ((unsigned int)0x50000000UL)
#define GPIOA (GPIO_TypeDef *) GPIOA_BASE
#define GPIO_PIN_5_POS 5
#define GPIO_PIN_8_POS 8
#define GPIO_2BIT_POS_MASK ((unsigned int)0x00000003U)
#define GPIO_1BIT_POS_MASK ((unsigned int)0x00000001U)
#define GPIO_MODE_OUTPUT ((unsigned int)0x00000001U) /*!< GPIO OutPut Mode */
#define GPIO_OUTPUT_TYPE_0 ((unsigned int)0x00000000U) /* PushPull */
#define GPIO_NOPUPD ((unsigned int)0x00000000U) /* No Pull up / down */
#define GPIO_SPEED_FREQ_VERY_HIGH ((unsigned int)0x00000003U) /*!< range 10 MHz to 35 MHz, please refer to the product datasheet */
#define LED2_ON ((unsigned int)0x00000001U)
#define LED2_OFF ((unsigned int)0x00000000U)
void delay(unsigned int delay_cnt)
{
volatile int counter = 0;
while(counter < delay_cnt) //delay loop
{
counter++;
}
}
void GPIO_Init(GPIO_TypeDef* pGPIO_Type, unsigned short pin, GPIO_TypeDef* initVal){
unsigned int position = pin;
//PA5 Mode
pGPIO_Type->MODER &= ~(GPIO_2BIT_POS_MASK << (position*2U));
pGPIO_Type->MODER |= initVal->MODER << (position*2U) ;
//OTYPER
pGPIO_Type->OTYPER &= ~(GPIO_1BIT_POS_MASK << position);
pGPIO_Type->OTYPER |= initVal->OTYPER << position ;
//OSPEEDR
pGPIO_Type->OSPEEDR &= ~(GPIO_2BIT_POS_MASK << (position*2U));
pGPIO_Type->OSPEEDR |= initVal->OSPEEDR << (position*2U) ;
//OPUPDR
pGPIO_Type->PUPDR &= ~(0x03U << (position*2U));
pGPIO_Type->PUPDR |= initVal->PUPDR << (position*2U) ;
}
void GPIO_Write_Pin(GPIO_TypeDef* pGPIO_Type, unsigned short pin, GPIO_PinState state)
{
unsigned int mode = 0x0U;
unsigned int reg = 0x0U;
reg = pGPIO_Type->ODR;
reg &= ~(GPIO_1BIT_POS_MASK << pin);
mode = state << pin;
pGPIO_Type->ODR = reg |= mode;
}
int main()
{
GPIO_TypeDef initVal;
GPIO_PinState pin_state = GPIO_PIN_RESET;
//RCC-GPIOA
RCC_IOPENR |= RCC_GPIOA_EN;
initVal.MODER = GPIO_MODE_OUTPUT;
initVal.OTYPER = GPIO_OUTPUT_TYPE_0;
initVal.OSPEEDR = GPIO_SPEED_FREQ_VERY_HIGH;
initVal.PUPDR = GPIO_NOPUPD;
GPIO_Init(GPIOA, GPIO_PIN_5_POS, &initVal);
GPIO_Write_Pin(GPIOA, GPIO_PIN_5_POS, pin_state);
GPIO_Init(GPIOA, GPIO_PIN_8_POS, &initVal);
GPIO_Write_Pin(GPIOA, GPIO_PIN_8_POS, (GPIO_PinState)!pin_state);
while(1)
{
delay(0x20000);
pin_state = (GPIO_PinState)(!pin_state);
GPIO_Write_Pin(GPIOA, GPIO_PIN_5_POS, pin_state);
GPIO_Write_Pin(GPIOA, GPIO_PIN_8_POS, (GPIO_PinState)!pin_state);
}
}
마지막으로 레지스터 정보를 배열에 저장하고 BSS/BSSR 레지스터를 사용해보자
//Structure & Array
typedef struct
{
volatile unsigned int MODER; /*!< GPIO port mode register, Address offset: 0x00 */
volatile unsigned int OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */
volatile unsigned int OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */
volatile unsigned int PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */
volatile unsigned int IDR; /*!< GPIO port input data register, Address offset: 0x10 */
volatile unsigned int ODR; /*!< GPIO port output data register, Address offset: 0x14 */
volatile unsigned int BSRR; /*!< GPIO port bit set/reset registerBSRR, Address offset: 0x18 */
volatile unsigned int LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */
volatile unsigned int AFR[2]; /*!< GPIO alternate function register, Address offset: 0x20-0x24 */
volatile unsigned int BRR; /*!< GPIO bit reset register, Address offset: 0x28 */
}GPIO_TypeDef;
typedef enum
{
GPIO_PIN_RESET = 0U,
GPIO_PIN_SET
} GPIO_PinState;
typedef enum
{
LED2 = 0,
USER_LED1,
}Led_TypeDef;
#define PERIPH_BASE (0x40000000UL) /*!< Peripheral base address in the alias region */
#define AHBPERIPH_BASE (PERIPH_BASE + 0x00020000UL)
#define RCC_BASE (AHBPERIPH_BASE + 0x00001000UL)
#define RCC_IOPENR *((volatile unsigned int*)(RCC_BASE + 0x0000002CUL))
#define RCC_GPIOA_EN ((unsigned int)0x00000001U)
//#define GPIO_PA5PIN_BASE (unsigned int)0x50000000UL
#define GPIOA_BASE ((unsigned int)0x50000000UL)
#define GPIOA (GPIO_TypeDef *) GPIOA_BASE
#define GPIO_PIN_5_POS 5
#define GPIO_PIN_8_POS 8
#define GPIO_NUMBER (16U)
#define GPIO_2BIT_POS_MASK ((unsigned int)0x00000003U)
#define GPIO_1BIT_POS_MASK ((unsigned int)0x00000001U)
#define GPIO_MODE_OUTPUT ((unsigned int)0x00000001U) /*!< GPIO OutPut Mode */
#define GPIO_OUTPUT_TYPE_0 ((unsigned int)0x00000000U) /* PushPull */
#define GPIO_NOPUPD ((unsigned int)0x00000000U) /* No Pull up / down */
#define GPIO_SPEED_FREQ_VERY_HIGH ((unsigned int)0x00000003U) /*!< range 10 MHz to 35 MHz, please refer to the product datasheet */
#define LED2_ON ((unsigned int)0x00000001U)
#define LED2_OFF ((unsigned int)0x00000000U)
#define LEDn 2
GPIO_TypeDef* LED_PORT[LEDn] = {GPIOA, GPIOA};
unsigned short LED_PIN[LEDn] = {GPIO_PIN_5_POS, GPIO_PIN_8_POS};
void delay(unsigned int delay_cnt);
void GPIO_Init(GPIO_TypeDef* pGPIO_Type, unsigned short pin, GPIO_TypeDef* initVal);
void GPIO_Write_Pin(GPIO_TypeDef* pGPIO_Type, unsigned short pin, GPIO_PinState state);
void GPIO_Toggle_Pin(GPIO_TypeDef* pGPIO_Type, unsigned short GPIO_Pin);
int main()
{
GPIO_TypeDef initVal;
GPIO_PinState pin_state = GPIO_PIN_RESET;
//RCC-GPIOA
RCC_IOPENR |= RCC_GPIOA_EN;
initVal.MODER = GPIO_MODE_OUTPUT;
initVal.OTYPER = GPIO_OUTPUT_TYPE_0;
initVal.OSPEEDR = GPIO_SPEED_FREQ_VERY_HIGH;
initVal.PUPDR = GPIO_NOPUPD;
GPIO_Init(LED_PORT[LED2], LED_PIN[LED2], &initVal);
GPIO_Write_Pin(LED_PORT[LED2], LED_PIN[LED2], pin_state);
GPIO_Init(LED_PORT[USER_LED1], LED_PIN[USER_LED1], &initVal);
GPIO_Write_Pin(LED_PORT[USER_LED1], LED_PIN[USER_LED1], (GPIO_PinState)!pin_state);
while(1)
{
delay(0x20000);
pin_state = (GPIO_PinState)(!pin_state);
GPIO_Toggle_Pin(LED_PORT[LED2], LED_PIN[LED2]);
GPIO_Toggle_Pin(LED_PORT[USER_LED1], LED_PIN[USER_LED1]);
}
}
void delay(unsigned int delay_cnt)
{
volatile int counter = 0;
while(counter < delay_cnt) //delay loop
{
counter++;
}
}
void GPIO_Init(GPIO_TypeDef* pGPIO_Type, unsigned short pin, GPIO_TypeDef* initVal){
unsigned int position = pin;
//PA5 Mode
pGPIO_Type->MODER &= ~(GPIO_2BIT_POS_MASK << (position*2U));
pGPIO_Type->MODER |= initVal->MODER << (position*2U) ;
//OTYPER
pGPIO_Type->OTYPER &= ~(GPIO_1BIT_POS_MASK << position);
pGPIO_Type->OTYPER |= initVal->OTYPER << position ;
//OSPEEDR
pGPIO_Type->OSPEEDR &= ~(GPIO_2BIT_POS_MASK << (position*2U));
pGPIO_Type->OSPEEDR |= initVal->OSPEEDR << (position*2U) ;
//OPUPDR
pGPIO_Type->PUPDR &= ~(0x03U << (position*2U));
pGPIO_Type->PUPDR |= initVal->PUPDR << (position*2U) ;
}
void GPIO_Write_Pin(GPIO_TypeDef* pGPIO_Type, unsigned short pin, GPIO_PinState state)
{
unsigned int mode = 0x0U;
unsigned int reg = 0x0U;
reg = pGPIO_Type->ODR;
reg &= ~(GPIO_1BIT_POS_MASK << pin);
mode = state << pin;
pGPIO_Type->ODR = reg |= mode;
}
void GPIO_Toggle_Pin(GPIO_TypeDef* pGPIO_Type, unsigned short GPIO_Pin)
{
unsigned int position = 0;
position = GPIO_1BIT_POS_MASK << (GPIO_Pin);
unsigned int odr;
/* get current Output Data Register value */
odr = pGPIO_Type->ODR;
/* Set selected pins that were at low level, and reset ones that were high */
pGPIO_Type->BSRR = ((odr & position) << GPIO_NUMBER) | (~odr & position);
}
끄읕!