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

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

[复制链接]
freemancn 发布时间:2019-8-17 18:13
阅读主题, 点击返回1楼
收藏 5 评论31 发布时间:2019-8-17 18:13
31个回答
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++配上这个开发环境生产力大大提高,代码的可复用性也大大提高.另外,我的项目已经投产了.



奔跑的蜗牛321 回答时间:2021-5-18 16:55:06
freemancn 发表于 2020-11-19 21:43
分享一个

#ifndef RCC_HPP_

还更新吗,能出一期环境搭建的教程吗,配一个Demo工程
123

所属标签

相似分享

官网相关资源

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