STM32 abstracting from CMSIS registers when configuring GPIO

As you know, CMSIS provides access to the registers of the microcontroller. This is good, but not very convenient. This article will focus on configuring GPIO. I / O ports are configured quite simply and if we are talking about one or two pins, you can use the registers directly. But if you need to configure several pins, and even more so dynamically change the configuration (this may be required, for example, to check the tightness of the lines to the plus when implementing work with I2C, and then to switch to work with hardware I2C), then it is much easier to wrap all the work with registers to the class, and use methods like setPin / resetPin.





Since the class with GPIO works, I decided to call it that. It has a GPIO constructor (GPIO_TypeDef * port) that accepts a port reference. There are also methods in the class:





  • void pinConf (uint8_ t pin_ nomber, uint8_ t pin_ mode); // pin operation mode





  • void setPin (uint8_ t pin_ nomber); // set 1





  • void resetPin (uint8_ t pin_ nomber); // reset pin





  • int getPin (uint8_ t pin_ nomber); // read the state of the pin (reg. IDR)





The class module consists of two files - gpio.h and gpio.cpp.





GPIO.H

#ifndef USER_LIB_GPIO_GPIO_H_
#define USER_LIB_GPIO_GPIO_H_

#include "stm32f103xb.h"

//---------------inputs-------------------------------------------------
#define INPUT_FLOATING 0x4 		//   
#define INPUT_PULL_UP 0x7F 		//    
#define INPUT_PULL_DOWN 0xFF 	//    ""
#define INPUT_ANALOG 0x0 			//  

//--------------outputs--------------------------------------------------
#define OUTPUT_OPEN_DRAIN 0x7 //   
#define OUTPUT_PUSH_PULL 0x3 	//  -

//--------------altarnate function---------------------------------------
#define AF_PUSH_PULL 0xB 			//  -   -
#define AF_OPEN_DRAIN 0xF 		//     
      
      



. GPIOx_CRL ( 0 7 ) GPIOx_CRH ( 8 15 ). 4 , . , , . .





class GPIO {

	public:

	GPIO( GPIO_TypeDef *port );
	
	void pinConf ( uint8_t pin_nomber, uint8_t pin_mode ); //   
	void setPin( uint8_t pin_nomber ); //  1  
	void resetPin( uint8_t pin_nomber ); //  
	int getPin ( uint8_t pin_nomber ); //    (reg. IDR)

	private:

	GPIO_TypeDef *GPIOx;
	int pin_m;


};

#endif /* USER_LIB_GPIO_GPIO_H_ */

      
      



GPIO. (GPIOA, GPIOB ..) GPIOx. , , .





, .





  • pinConf ( uint8_t pin_nomber, uint8_t pin_mode ) , .





  • setPin( uint8_t pin_nomber ) 1. .





  • resetPin( uint8_t pin_nomber ) . .





  • getPin ( uint8_t pin_nomber ) ( IDR)





GPIO.CPP

#define INPUT_PULL_UP_DOWN 0x8 //    
#define GPIO_BITS_MASK 0xF //     

GPIO::GPIO(GPIO_TypeDef *port){

	this->GPIOx = port;
//     APB1
	if ( port == GPIOA){

			RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
			return;
	}

	if ( port == GPIOB ){

			RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
			return;
	}

	if ( port == GPIOC ){
			RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
			return;
	}

	if ( port == GPIOD ){
			RCC->APB2ENR |= RCC_APB2ENR_IOPDEN;
			return;
	}

	if ( port == GPIOE ){
			RCC->APB2ENR |= RCC_APB2ENR_IOPEEN;
			return;

	}

return;

}
      
      



.





void GPIO::pinConf ( uint8_t pin_nomber, uint8_t pin_mode ){

	this->pin_m = pin_mode; //   set/reset Pin    -
	uint8_t offset; //   
	uint8_t mode; 

	//      pin_mode
	if ( ( pin_mode == INPUT_PULL_UP ) || ( pin_mode == INPUT_PULL_DOWN ) ){

		mode = INPUT_PULL_UP_DOWN;
	}//if

	if ( pin_nomber < 8 ){

		offset = pin_nomber * 4;
		this->GPIOx->CRL &= ~( GPIO_BITS_MASK << offset );
		this->GPIOx->CRL |= ( mode << offset );
	} // if
	else if ( pin_nomber > 7 ){

		offset = ( pin_nomber - 8 ) * 4;
		this->GPIOx->CRH &= ~( GPIO_BITS_MASK << offset );
		this->GPIOx->CRH |= ( mode << offset );

	} // else

	//   -      ODR   1
	if ( pin_mode == INPUT_PULL_UP ){

		GPIOx->ODR |= ( 1 << pin_nomber );

	}

	/* . .     INPUT_PULL_DOWN      0
	 *    ,     INPUT_PULL_UP
	 *   -      INPUT_PULL_DOWN.    
	 *  ODR  1        INPUT_PULL_UP
	 */
	if ( pin_mode == INPUT_PULL_DOWN ){

		GPIOx->ODR &= ~( 1 << pin_nomber );

	}
return;
} //pinConf

      
      



pin_m. , setPin()/resetPin() , .





. pin_mode , ODR 1 0.





if ( pin_nomber < 8 ) if ( pin_nomber > 7 ) CRL CRH , , 4 , offset. GPIO BIT MASK, .





if ( pin_mode == INPUT_PULL_UP ) - , , ODR . , .





void GPIO::setPin( uint8_t pin_nomber ){

	//      -   
	// ..       -
	if ( ( this->pin_m == AF_PUSH_PULL) || ( this->pin_m == AF_OPEN_DRAIN ) ){

		return;

	}// if

	this->GPIOx->BSRR = ( 1 << pin_nomber );
return;
}
      
      



setPin() . , . BSSR 1 .





void GPIO::resetPin( uint8_t pin_nomber ){

	//      -   
	// ..       -
	if ( ( this->pin_m == AF_PUSH_PULL) || ( this->pin_m == AF_OPEN_DRAIN ) ){

		return;

	}// if

	this->GPIOx->BRR = ( 1 << pin_nomber );
return;
}
      
      



resetPin() , , BRR .





int GPIO::getPin ( uint8_t pin_nomber ){

	uint16_t mask;
	mask = ( 1<< pin_nomber);

	if ( (this->GPIOx->IDR) & mask) return 1;

	else return 0;
}
      
      



getPin() , IDR . - 1, 0.





:





GPIO *port = new GPIO( GPIOC ); //   ,   GPIOC
port->pinConf( 13, OUTPUT_PUSH_PULL ); //   -
port->setPin (13); //    1
port->resetPin (13); //  
int value;
value = port->getPin (13); //   
      
      



. - , . , -. , , , GPIO. .








All Articles