Why use C + + to develop MCU program
In the embedded system with microprocessor as the core, most of them use C language for program design, but with the increase of system scale, the program is more and more complex and maintenance is more and more difficult. Using C + + for development has the following advantages (provided that the compiler must support c + +, otherwise it is empty talk):
- Reduced parameter passing. In C + +, the data used can be used as data members, which can avoid the parameter transfer process of the function and improve the execution speed and efficiency.
- Safer. C + + encapsulates data and methods, which can hide the details of class implementation and avoid the exposure of internal data structure.
- Can reduce naming conflicts. C language has no concept of namespace, which is easy to lead to name conflict.
Of course, in C language, the function pointer can also be defined in the structure to achieve the effect similar to C + + encapsulation. However, this method is troublesome, and there is no access control in C language. All members in the structure can be accessed directly, which is not conducive to hiding the details of the implementation. Moreover, if the caller is not familiar with the structure and accesses members that should not be accessed, the consequences are disastrous.
Here I take stm32l151c8t6 as an example to share with you how to use C + + for MCU development. The compiler uses MDK and the firmware library is stm32l1xx_ StdPeriph_ Lib_ V1. three point one
Viewing object-oriented programming style from running water lamp
The following are examples of process oriented and object-oriented programming styles:
Process oriented program style:
int main(){ BSP_Init(); while(1){ delay(2000); GPIO_SetBits(LED1); delay(2000); GPIO_ResetBits(LED1); } return 0; }
Object oriented program style:
int main(){ CBsp bsp; bsp.Init(); CLed led1(LED1); while(1){ bsp.delay_ms(2000); led1.isOn()?led1.Off():led1.On(); } return 0; }
It can be seen that the idea of object-oriented program style is clearer. For the business code in while(1), if the underlying IO changes, the process oriented program modification involves the modification of business code. For the object-oriented program, only the relevant classes need to be modified without modifying the business code, which greatly reduces the maintenance cost of complex programs.
Moreover, due to the encapsulation of related functions and data into related classes, the program has better classification and hierarchy. Let me introduce our first class CBsp.
The first C + + class ---- CBsp
Functions of CBsp:
-
Initialize the resources related to the system: such as setting the interrupt vector attribute and debugging the initialization of the serial port.
-
Provide delay operation for users.
This is the CBsp class:
class CBsp{ public: void Init(void); void delay_us(uint32_t n_ms); void delay_ms(uint16_t n_ms); private: void sys_debug_Init(void); void SysTick_Init(void); };
Specific implementation:
#include "Bsp.h" #ifdef __GNUC__ #define PUTCHAR_PROTOTYPE int __io_putchar (int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *f) #endif extern "C" PUTCHAR_PROTOTYPE { /* Place your implementation of fputc here */ /* e.g. write a character to the USART */ USART_SendData(USART2, (uint8_t) ch); /* Loop until transmit data register is empty */ while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET) {} return ch; } static uint8_t fac_us=0; //Delay multiplier static uint16_t fac_ms=0; //ms delay multiplier void CBsp::Init(void){ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); sys_debug_Init(); SysTick_Init(); } /* *Configure systick as a 24Bit down counter for general delay purposes only *CPU Dominant frequency = 32MHz */ void CBsp::SysTick_Init(void) { //uint32_t reload = 0; SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;//systick_clk = 4MHz fac_us = 4;//1us requires 4 systick clocks fac_ms = (uint16_t)fac_us*1000; } /* Maximum 4194304us */ void CBsp::delay_us(uint32_t n_us) { uint32_t temp; SysTick->LOAD=n_us*fac_us; //Time loading SysTick->VAL=0x00; //Clear counter SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //Start counting down do { temp=SysTick->CTRL; }while((temp&0x01)&&!(temp&(1<<16))); //Waiting time arrives SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //Turn off counter SysTick->VAL =0X00; //Clear counter } /* Maximum 4194ms */ void CBsp::delay_ms(uint16_t n_ms) { uint32_t temp; SysTick->LOAD=(uint32_t)n_ms*fac_ms; //Time loading (systick - > load is 24bit) SysTick->VAL =0x00; //Clear counter SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //Start counting down do { temp=SysTick->CTRL; }while((temp&0x01)&&!(temp&(1<<16))); //Waiting time arrives SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //Turn off counter SysTick->VAL =0X00; //Clear counter } void CBsp::sys_debug_Init(void) { GPIO_InitTypeDef uart_gpio; USART_InitTypeDef debug_uart; /* config for usart2 */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); /* Connect PXx to USARTx_Tx */ GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); /* Connect PXx to USARTx_Rx */ GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); /* Configure USART Tx as alternate function push-pull */ uart_gpio.GPIO_Pin = GPIO_Pin_2; uart_gpio.GPIO_Mode = GPIO_Mode_AF; uart_gpio.GPIO_Speed = GPIO_Speed_40MHz; uart_gpio.GPIO_OType = GPIO_OType_PP; uart_gpio.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOA, &uart_gpio); /* Configure USART Rx as alternate function push-pull */ uart_gpio.GPIO_Pin = GPIO_Pin_3; GPIO_Init(GPIOA, &uart_gpio); debug_uart.USART_BaudRate = 115200; debug_uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None; debug_uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; debug_uart.USART_Parity = USART_Parity_No; debug_uart.USART_StopBits = USART_StopBits_1; debug_uart.USART_WordLength = USART_WordLength_8b; /* USART configuration */ USART_Init(USART2, &debug_uart); USART_Cmd(USART2,ENABLE); USART_ClearFlag(USART2, USART_FLAG_TC); USART_ClearITPendingBit(USART2,USART_IT_RXNE); USART_ITConfig(USART2,USART_IT_RXNE,DISABLE); }
Call example:
int main(void){ CBsp bsp; bsp.Init(); bsp.delay_ms(1000); while (1); return 0; }
reference
- Design of stm32 embedded system based on cortex-m3
- CBsp class code: http://download.csdn.net/detail/winsbb/9869686