你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

用C++写单片机程序STM32F103+自建固件库+FreeRTOS gcc编译器  

[复制链接]
freemancn 发布时间:2019-8-17 18:13
阅读主题, 点击返回1楼
收藏 4 评论30 发布时间:2019-8-17 18:13
30个回答
freemancn 回答时间:2020-11-19 21:43:03
mylovemcu 发表于 2020-11-13 14:08
老师去哪了  怎么不更新了  搞一个库上来学习一下
想看看你的顶层库怎么写的  我现在也在用C++  底层库太费 ...

分享一个

#ifndef RCC_HPP_
#define RCC_HPP_

#include "STM32F103.h"

namespace MCU
{
        namespace STM32F103
        {
                struct RegisterRCC
                {
                        volatile union
                        {
                                volatile uint32_t Value;
                        
                                volatile struct
                                {
                                        volatile uint32_t HSION : 1;
                                        volatile const uint32_t HSIRDY : 1;
                                        volatile uint32_t RESERVED1 : 1;
                                        volatile uint32_t HSITRIM : 5;
                                        volatile const uint32_t HSICAL : 8;
                                        volatile uint32_t HSEON : 1;
                                        volatile const uint32_t HSERDY : 1;
                                        volatile uint32_t HSEBYP : 1;
                                        volatile uint32_t CSSON : 1;
                                        volatile uint32_t RESERVDE2 : 4;
                                        volatile uint32_t PLLON : 1;
                                        volatile const uint32_t PLLRDY : 1;
                                        volatile uint32_t RESERVDE3 : 6;
                                }Bit;
                        }CR;

                        volatile union
                        {
                                volatile uint32_t Value;
                        
                                volatile struct
                                {
                                        volatile uint32_t SW : 2;
                                        volatile const uint32_t SWS : 2;
                                        volatile uint32_t HPRE : 4;
                                        volatile uint32_t PPRE1 : 3;
                                        volatile uint32_t PPRE2 : 3;
                                        volatile uint32_t ADCPRE : 2;
                                        volatile uint32_t PLLSRC : 1;
                                        volatile uint32_t PLLXTPRE : 1;
                                        volatile uint32_t PLLMUL : 4;
                                        volatile uint32_t USBPRE : 1;
                                        volatile uint32_t RESERVED1 : 1;
                                        volatile uint32_t MCO : 3;
                                        volatile uint32_t RESERVED2 : 5;
                                }Bit;
                        }CFGR;
               
                        volatile union
                        {
                                volatile uint32_t Value;
                        
                                volatile struct
                                {
                                        volatile const uint32_t LSIRDYF : 1;
                                        volatile const uint32_t LSERDYF : 1;
                                        volatile const uint32_t HSIRDYF : 1;
                                        volatile const uint32_t HSERDYF : 1;
                                        volatile const uint32_t PLLRDYF : 1;
                                        volatile const uint32_t PLL2RDYF : 1;
                                        volatile const uint32_t PLL3RDYF : 1;
                                        volatile const uint32_t CSSF : 1;
                                        volatile uint32_t LSIRDYIE : 1;
                                        volatile uint32_t LSERDYIE : 1;
                                        volatile uint32_t HSIRDYIE : 1;
                                        volatile uint32_t HSERDYIE : 1;
                                        volatile uint32_t PLLRDYIE : 1;
                                        volatile const uint32_t PLL2RDYE : 1;
                                        volatile const uint32_t PLL3RDYE : 1;
                                        volatile uint32_t RESERVED1 : 1;
                                        volatile uint32_t LSIRDYC : 1;
                                        volatile uint32_t LSERDYC : 1;
                                        volatile uint32_t HISRDYC : 1;
                                        volatile uint32_t HSERDYC : 1;
                                        volatile uint32_t PLLRDYC : 1;
                                        volatile uint32_t PLL2RDYC : 1;
                                        volatile uint32_t PLL3RDYC : 1;
                                        volatile uint32_t CSSC : 1;
                                        volatile uint32_t RESERVED2 : 8;
                                }Bit;
                        }CIR;
               
                        volatile union
                        {
                                volatile uint32_t Value;
                        
                                volatile struct
                                {
                                        volatile uint16_t AFIORST : 1;
                                        volatile uint16_t RESERVED1 : 1;
                                        volatile uint16_t IOPARST : 1;
                                        volatile uint16_t IOPBRST : 1;
                                        volatile uint16_t IOPCRST : 1;
                                        volatile uint16_t IOPDRST : 1;
                                        volatile uint16_t IOPERST : 1;
                                        volatile uint16_t IOPFRST : 1;
                                        volatile uint16_t IOPGRST : 1;
                                        volatile uint16_t ADC1RST : 1;
                                        volatile uint16_t ADC2RST : 1;
                                        volatile uint16_t TIM1RST : 1;
                                        volatile uint16_t SPI1RST : 1;
                                        volatile uint16_t TIM8RST : 1;
                                        volatile uint16_t USART1RST : 1;
                                        volatile uint16_t ADC3RST : 1;
                                        volatile uint16_t RESERVED2 : 16;
                                }Bit;
                        }APB2RSTR;
               
                        volatile union
                        {
                                volatile uint32_t Value;
                        
                                volatile struct
                                {
                                        volatile uint32_t TIM2RST : 1;
                                        volatile uint32_t TIM3RST : 1;
                                        volatile uint32_t TIM4RST : 1;
                                        volatile uint32_t TIM5RST : 1;
                                        volatile uint32_t TIM6RST : 1;
                                        volatile uint32_t TIM7RST : 1;
                                        volatile uint32_t RESERVED1 : 2;
                                        volatile uint32_t RESERVED2 : 3;
                                        volatile uint32_t WWDGRST : 1;
                                        volatile uint32_t RESERVED3 : 2;
                                        volatile uint32_t SPI2RST : 1;
                                        volatile uint32_t SPI3RST : 1;
                                        volatile uint32_t RESERVED4 : 1;
                                        volatile uint32_t USART2RST : 1;
                                        volatile uint32_t USART3RST : 1;
                                        volatile uint32_t USART4RST : 1;
                                        volatile uint32_t USART5RST : 1;
                                        volatile uint32_t I2C1RST : 1;
                                        volatile uint32_t I2C2RST : 1;
                                        volatile uint32_t USBRST : 1;
                                        volatile uint32_t RESERVED5 : 1;
                                        volatile uint32_t CANRST : 1;
                                        volatile uint32_t RESERVED6 : 1;
                                        volatile uint32_t BKPRST : 1;
                                        volatile uint32_t PWRRST : 1;
                                        volatile uint32_t DACRST : 1;
                                        volatile uint32_t RESERVED7 : 2;
                                }Bit;
                        }APB1RSTR;
               
                        volatile union
                        {
                                volatile uint32_t Value;
                        
                                volatile struct
                                {
                                        volatile uint16_t DMA1EN : 1;
                                        volatile uint16_t DMA2EN : 1;
                                        volatile uint16_t SRAMEN : 1;
                                        volatile uint16_t RESERVED1 : 1;
                                        volatile uint16_t FLITFEN : 1;
                                        volatile uint16_t RESERVED2 : 1;
                                        volatile uint16_t CRCEN : 1;
                                        volatile uint16_t RESERVED3 : 1;
                                        volatile uint16_t FSMCEN : 1;
                                        volatile uint16_t RESERVED4 : 1;
                                        volatile uint16_t SDIOEN : 1;
                                        volatile uint16_t RESERVED5 : 5;
                                        volatile uint16_t RESERVED6 : 16;
                                }Bit;
                        }AHBENR;
               
                        volatile union
                        {
                                volatile uint32_t Value;
                        
                                volatile struct
                                {
                                        volatile uint16_t AFIOEN : 1;
                                        volatile uint16_t RESERVED1 : 1;
                                        volatile uint16_t IOPAEN : 1;
                                        volatile uint16_t IOPBEN : 1;
                                        volatile uint16_t IOPCEN : 1;
                                        volatile uint16_t IOPDEN : 1;
                                        volatile uint16_t IOPEEN : 1;
                                        volatile uint16_t IOPFEN : 1;
                                        volatile uint16_t IOPGEN : 1;
                                        volatile uint16_t ADC1EN : 1;
                                        volatile uint16_t ADC2EN : 1;
                                        volatile uint16_t TIM1EN : 1;
                                        volatile uint16_t SPI1EN : 1;
                                        volatile uint16_t TIM8EN : 1;
                                        volatile uint16_t USART1EN : 1;
                                        volatile uint16_t ADC3EN : 1;
                                        volatile uint16_t RESERVED2 : 16;
                                }Bit;
                        }APB2ENR;
               
                        volatile union
                        {
                                volatile uint32_t Value;
                        
                                volatile struct
                                {
                                        volatile uint32_t TIM2EN : 1;
                                        volatile uint32_t TIM3EN : 1;
                                        volatile uint32_t TIM4EN : 1;
                                        volatile uint32_t TIM5EN : 1;
                                        volatile uint32_t TIM6EN : 1;
                                        volatile uint32_t TIM7EN : 1;
                                        volatile uint32_t RESERVED1 : 2;
                                        volatile uint32_t RESERVED2 : 3;
                                        volatile uint32_t WWDGEN : 1;
                                        volatile uint32_t RESERVED3 : 2;
                                        volatile uint32_t SPI2EN : 1;
                                        volatile uint32_t SPI3EN : 1;
                                        volatile uint32_t RESERVED4 : 1;
                                        volatile uint32_t USART2EN : 1;
                                        volatile uint32_t USART3EN : 1;
                                        volatile uint32_t USART4EN : 1;
                                        volatile uint32_t USART5EN : 1;
                                        volatile uint32_t I2C1EN : 1;
                                        volatile uint32_t I2C2EN : 1;
                                        volatile uint32_t USBEN : 1;
                                        volatile uint32_t RESERVED5 : 1;
                                        volatile uint32_t CANEN : 1;
                                        volatile uint32_t RESERVED6 : 1;
                                        volatile uint32_t BKPEN : 1;
                                        volatile uint32_t PWREN : 1;
                                        volatile uint32_t DACEN : 1;
                                        volatile uint32_t RESERVED7 : 2;
                                }Bit;
                        }APB1ENR;
               
                        volatile union
                        {
                                volatile uint32_t Value;
                        
                                volatile struct
                                {
                                        volatile uint32_t LSEON : 1;
                                        volatile const uint32_t LSERDY : 1;
                                        volatile uint32_t LSEBYP : 1;
                                        volatile uint32_t RESERVED1 : 5;
                                        volatile uint32_t RTCSEL : 2;
                                        volatile uint32_t RESERVED2 : 5;
                                        volatile uint32_t RTCEN : 1;
                                        volatile uint32_t BDRST : 1;
                                        volatile uint32_t RESERVED3 : 7;
                                        volatile uint32_t RESERVED4 : 8;
                                }Bit;
                        }BDCR;
               
                        volatile union
                        {
                                volatile uint32_t Value;
                        
                                volatile struct
                                {
                                        volatile uint32_t LSION : 1;
                                        volatile const uint32_t LSIRDY : 1;
                                        volatile uint32_t RESERVED1 : 6;
                                        volatile uint32_t RESERVED2 : 8;
                                        volatile uint32_t RESERVED3 : 8;
                                        volatile uint32_t RMVF : 1;
                                        volatile uint32_t RESERVED4 : 1;
                                        volatile uint32_t PINRSTF : 1;
                                        volatile uint32_t PORRSTF : 1;
                                        volatile uint32_t SFTRSTF : 1;
                                        volatile uint32_t IWDGRSTF : 1;
                                        volatile uint32_t WWDGRSTF : 1;
                                        volatile uint32_t LPWRRSTF : 1;
                                }Bit;
                        }CSR;
                };
        
                enum RCC_PLL_MUL
                {
                        RCC_PLL_MUL2  = 0b0000,
                        RCC_PLL_MUL3  = 0b0001,
                        RCC_PLL_MUL4  = 0b0010,
                        RCC_PLL_MUL5  = 0b0011,
                        RCC_PLL_MUL6  = 0b0100,
                        RCC_PLL_MUL7  = 0b0101,
                        RCC_PLL_MUL8  = 0b0110,
                        RCC_PLL_MUL9  = 0b0111,
                        RCC_PLL_MUL10 = 0b1000,
                        RCC_PLL_MUL11 = 0b1001,
                        RCC_PLL_MUL12 = 0b1010,
                        RCC_PLL_MUL13 = 0b1011,
                        RCC_PLL_MUL14 = 0b1100,
                        RCC_PLL_MUL15 = 0b1101,
                        RCC_PLL_MUL16 = 0b1110,
                };
               
                enum RCC_PLL_XTPRE
                {
                        RCC_PLL_XTPRE_DIV1 = 0b0,
                        RCC_PLL_XTPRE_DIV2 = 0b1,
                };
               
                enum RCC_PLL_SRC
                {
                        RCC_PLL_SRC_HSI_DIV2 = 0b0,
                        RCC_PLL_SRC_HSE      = 0b1,
                };
               
                enum RCC_HPRE
                {
                        RCC_HPRE_DIV1   = 0b0000,
                        RCC_HPRE_DIV2   = 0b1000,
                        RCC_HPRE_DIV4   = 0b1001,
                        RCC_HPRE_DIV8   = 0b1010,
                        RCC_HPRE_DIV16  = 0b1011,
                        RCC_HPRE_DIV64  = 0b1100,
                        RCC_HPRE_DIV128 = 0b1101,
                        RCC_HPRE_DIV256 = 0b1110,
                        RCC_HPRE_DIV512 = 0b1111,
                };
               
                enum RCC_PPRE
                {
                        RCC_PPRE_DIV1  = 0b000,
                        RCC_PPRE_DIV2  = 0b100,
                        RCC_PPRE_DIV4  = 0b101,
                        RCC_PPRE_DIV8  = 0b110,
                        RCC_PPRE_DIV16 = 0b111,
                };
               
                enum RCC_SW
                {
                        RCC_SW_HSI = 0b00,
                        RCC_SW_HSE = 0b01,
                        RCC_SW_PLL = 0b10,
                };
               
                class CRCC
                {
                public:
                        //保存外部晶体频率 在EnableHSE方法中初始化 用于计算系统频率
                        static uint32_t HSE;
                        
                        volatile struct RegisterRCC *pRegister = (volatile struct RegisterRCC *)(RCC_BASE);
                        
                        //开启外部高速时钟并等待时钟就绪,如果时钟不能就绪则一直等待
                        //HSE:晶体频率 单位:Hz
                        void EnableHSE(uint32_t HSE)
                        {
                                CRCC::HSE = HSE;
                                
                                this->pRegister->CR.Bit.HSEON = 1;
                                while(!this->pRegister->CR.Bit.HSERDY);
                        }
                        
                        //设置PLL参数,必须在PLL关闭的状态下
                        void SetPLL(RCC_PLL_MUL MUL, RCC_PLL_XTPRE XTPRE, RCC_PLL_SRC SRC)
                        {
                                this->pRegister->CFGR.Bit.PLLMUL = MUL;
                                this->pRegister->CFGR.Bit.PLLXTPRE = XTPRE;
                                this->pRegister->CFGR.Bit.PLLSRC = SRC;
                        }
                        
                        //开启PLL时钟并等待时钟就绪,如果时钟不能就绪则一直等待
                        void EnablePLL(void)
                        {
                                this->pRegister->CR.Bit.PLLON = 1;
                                while(!this->pRegister->CR.Bit.PLLRDY);
                        }
                        
                        //切换系统时钟源并等待切换就绪,如果切换不能就绪则一直等待
                        void SetSysClkSource(RCC_SW SW)
                        {
                                this->pRegister->CFGR.Bit.SW = SW;
                                while(this->pRegister->CFGR.Bit.SWS != SW);
                        }
                        
                        //获取系统时钟频率 单位:Hz
                        uint32_t GetSYSCLK(void)
                        {
                                if(this->pRegister->CFGR.Bit.SWS == RCC_SW_HSI)
                                {
                                        //系统时钟为HSI
                                        return 8000000;
                                }
                                else if(this->pRegister->CFGR.Bit.SWS == RCC_SW_HSE)
                                {
                                        //系统时钟为HSE
                                        return CRCC::HSE;
                                }
                                else if(this->pRegister->CFGR.Bit.SWS == RCC_SW_PLL)
                                {
                                        //系统时钟为PLL
                                        uint32_t SRC, XTPRE, MUL;
                                       
                                        if(this->pRegister->CFGR.Bit.PLLSRC == RCC_PLL_SRC_HSI_DIV2)
                                        {
                                                //PPL输入时钟源为HSI/2
                                                SRC = 8000000;
                                                XTPRE = 2;
                                        }
                                        else
                                        {
                                                //PLL输入时钟源为HSE
                                                SRC = CRCC::HSE;
                                                
                                                if(this->pRegister->CFGR.Bit.PLLXTPRE == RCC_PLL_XTPRE_DIV1)
                                                {
                                                        //PLL输入时钟源为HSE/2
                                                        XTPRE = 1;
                                                }
                                                else
                                                {
                                                        //PLL输入时钟源为HSE/2
                                                        XTPRE = 2;
                                                }
                                        }
                                       
                                        switch((uint32_t)this->pRegister->CFGR.Bit.PLLMUL)
                                        {
                                                case RCC_PLL_MUL2: MUL = 2; break;
                                                case RCC_PLL_MUL3: MUL = 3; break;
                                                case RCC_PLL_MUL4: MUL = 4; break;
                                                case RCC_PLL_MUL5: MUL = 5; break;
                                                case RCC_PLL_MUL6: MUL = 6; break;
                                                case RCC_PLL_MUL7: MUL = 7; break;
                                                case RCC_PLL_MUL8: MUL = 8; break;
                                                case RCC_PLL_MUL9: MUL = 9; break;
                                                case RCC_PLL_MUL10: MUL = 10; break;
                                                case RCC_PLL_MUL11: MUL = 11; break;
                                                case RCC_PLL_MUL12: MUL = 12; break;
                                                case RCC_PLL_MUL13: MUL = 13; break;
                                                case RCC_PLL_MUL14: MUL = 14; break;
                                                case RCC_PLL_MUL15: MUL = 15; break;
                                                case RCC_PLL_MUL16: MUL = 16; break;
                                                default: MUL = 16; break;
                                        }
                                       
                                        return SRC / XTPRE * MUL;
                                }
                                else
                                        return 8000000;
                        }
                        
                        //获取AHB总线频率 单位:Hz
                        uint32_t GetHCLK(void)
                        {
                                uint32_t Prescaler;
                                
                                switch((uint32_t)this->pRegister->CFGR.Bit.HPRE)
                                {
                                        case RCC_HPRE_DIV1: Prescaler = 1; break;
                                        case RCC_HPRE_DIV2: Prescaler = 2; break;
                                        case RCC_HPRE_DIV4: Prescaler = 4; break;
                                        case RCC_HPRE_DIV8: Prescaler = 8; break;
                                        case RCC_HPRE_DIV16: Prescaler = 16; break;
                                        case RCC_HPRE_DIV64: Prescaler = 64; break;
                                        case RCC_HPRE_DIV128: Prescaler = 128; break;
                                        case RCC_HPRE_DIV256: Prescaler = 256; break;
                                        case RCC_HPRE_DIV512: Prescaler = 512; break;
                                        default: Prescaler = 1; break;
                                }
                                
                                return this->GetSYSCLK() / Prescaler;
                        }
                        
                        //获取APB1总线频率 单位:Hz
                        uint32_t GetPCLK1(void)
                        {
                                uint32_t Prescaler;
                                
                                switch((uint32_t)this->pRegister->CFGR.Bit.PPRE1)
                                {
                                        case RCC_PPRE_DIV1:        Prescaler = 1; break;
                                        case RCC_PPRE_DIV2:        Prescaler = 2; break;
                                        case RCC_PPRE_DIV4: Prescaler = 4; break;
                                        case RCC_PPRE_DIV8: Prescaler = 8; break;
                                        case RCC_PPRE_DIV16: Prescaler = 16; break;
                                        default: Prescaler = 1; break;
                                }
                                
                                return this->GetHCLK() / Prescaler;
                        }
                        
                        //获取APB2总线频率 单位:Hz
                        uint32_t GetPCLK2(void)
                        {
                                uint32_t Prescaler;
                                
                                switch((uint32_t)this->pRegister->CFGR.Bit.PPRE2)
                                {
                                        case RCC_PPRE_DIV1: Prescaler = 1; break;
                                        case RCC_PPRE_DIV2: Prescaler = 2; break;
                                        case RCC_PPRE_DIV4: Prescaler = 4; break;
                                        case RCC_PPRE_DIV8: Prescaler = 8; break;
                                        case RCC_PPRE_DIV16: Prescaler = 16; break;
                                        default: Prescaler = 1; break;
                                }
                                
                                return this->GetHCLK() / Prescaler;
                        }
                };
               
                uint32_t CRCC::HSE = 0;
        }
}

#endif // !RCC_HPP_

这是对RCC的封装,其实对寄存器的封装只是C++写单片机的小问题.还有几个问题要解决.
第一:如何把中断连接到任何对象的方法,这个问题本质就是如何利用指针调用对象方法,实现后可以更好的发挥面向对象的多态思路,实现一些高灵活度的编程.我用模板类实现了一个类似C#中的委托对象,然后利用这个对象还可以实现类似C#中的事件,完成消息的多播.当然这是需要付出代价的,这个模板类要用到虚函数表,经过实测这个消耗是可以接受的,多1us左右吧.这个模板类的实现具体可以用Bing国际版搜索FastDelegate.
第二:如何new和delete,这个必须通过OS实现.我使用FreeRTOS,然后全局重载new和delete运算符到pvPortMalloc和pvPortFree.不过能定义声明的对象尽量定义声明,不要频繁new和delete因为FreeRTOS的内存管理还是很弱鸡的.实现的目的只是为了提高程序的灵活度.让一些代码可以更快地适配一些硬件.我通常都是只new不delete

为了更好更快地更换MCU,应该定义一个HAL层,里面全是虚基类,抽象类似但又不同的硬件.然后顶层基于HAL开发,底层继承HAL的虚基类并做具体实现.不过虚基类又牵涉虚函数表,会有性能损失.在对性能要求高的地方还是针对不同的硬件进行直接控制.

为了更好的进行C++编程,我用gcc编译器.使用这个编译器时一定要注意,编译优化可能导致运行结果不正确,我通常是用O2或Os,一些特殊的函数还需要标记为O0.开发环境是Visual Studio 2019(个人版 免费) + VisualGDB(我买了正版).VisualGDB V5.5R2这个版本真是超级好用,自动完成,代码着色,代码格式化都是杠杠的.这个环境中在线仿真是ST-Link 2 + OpenOCD,可以设置端点,可以实时读取寄存器值,等等.

总之,C++配上这个开发环境生产力大大提高,代码的可复用性也大大提高.另外,我的项目已经投产了.



1234

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版