這一章編寫PWM程序,使用TIM3以兩個通道,完全映射到PC6和PC7,除普通PWM輸出外,增加移相正交PWM功能,為后面的編碼器計數(shù)模式提供信號源。
PWM.h
#ifndef __PWM__
#define __PWM__
extern "C" { // 兼容C,按C語言編譯,Keil5中的包含文件已經(jīng)加入了C++兼容,不用再加這一段
#pragma diag_remark 368 //消除 warning: #368-D: class " #include "stm32f10x.h" #pragma diag_default 368 // 恢復368號警告 } #include "Timer.h" #include "IO.h" class PWM : public IO, public Timer { // Construction public: PWM(); // Properties public: protected: private: // Methods public: void setData(u16 ch, u16 nData); void orthogonal( u16 nArr, u16 nPrescaler ); // 生成正交波型 void orthogonal2( u16 nArr, u16 nPrescaler ); // 生成反向正交波型 // Overwrite public: }; #endif PWM.cpp /** ****************************************************************************** * @file PWM.cpp * @author Mr. Hu * @version V1.0.0 STM32F103VET6 * @date 05/21/2019 * @brief PWM * @IO * TIM3 定時器3 * PC6 PWM1 * PC7 PWM2 * PC8 PWM預留 * PC9 PWM預留 ****************************************************************************** * @remarks * 1KHz PWM 刻度1000 * 只用TIM3通道1和2,對應PC6和PC7 * * 參考資料: * https://www.cnblogs.com/zhoubatuo/p/6135103.html 有端口分配圖 * https://blog.csdn.net/qq_36554582/article/details/81239628 完整代碼 * https://blog.csdn.net/zqingyaa/article/details/86255208 分頻計算方法 */ /* Includes ------------------------------------------------------------------*/ extern "C" { // 兼容C,按C語言編譯,Keil5中的包含文件已經(jīng)加入了C++兼容,不用再加這一段 #pragma diag_remark 368 //消除 warning: #368-D: class " #include "stm32f10x_tim.h" #pragma diag_default 368 // 恢復368號警告 } #include "PWM.h" /** * @date 05/21/2019 * @brief PWM,脈寬調(diào)制 : * IO(GPIOC, GPIO_Pin_6 | GPIO_Pin_7, GPIO_Mode_AF_PP, 1) * 初始化PC6、PC7,GPIO_Mode_AF_PP復用輸出 * 最后一個參數(shù)1表示初始化為高電位,但實際是低電位 * 默認產(chǎn)生同相PWM,頻率1k,占空比調(diào)節(jié)范圍0-999,用setData設置 * 調(diào)用成員函數(shù)orthogonal時,兩個輸出端PC6、PC7產(chǎn)生正交PWM波形,占空比為50%, * 主要用于模擬編碼輸出信號。 * orthogonal2產(chǎn)生反向的正交波形,用于編碼器遞減計數(shù)。 * @param None * @retval None */ PWM::PWM() : IO(GPIOC, GPIO_Pin_6 | GPIO_Pin_7, GPIO_Mode_AF_PP, 1) // GPIOx, nPin, GPIO_Mode_AF_PP 上拉, 2 輸入時無效 , Timer(TIM3) // 用TIM3 { RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);// 使能復用輸出,不映射端口時可以不用這一句 GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); // 把TIM3重映射到PC6-9,只用PC6-7。如果不映射,不要這一句 // 同相PWM,兩個通道同相 TIM_TimeBaseStructure.TIM_Period = 1000-1; // 自動重裝載寄存器的值 // https://blog.csdn.net/zqingyaa/article/details/86255208 分頻計算方法 TIM_TimeBaseStructure.TIM_Prescaler = 72-1; // TIMX預分頻的值,主頻72M,刻度100,分頻720,得到1kHz的PWM TIM_TimeBaseInit(m_pTIMx, &TIM_TimeBaseStructure); // 初始化 // 設置CH1的PWM模式,輸出GPC6 TIM_OCInitTypeDef TIM_OCInitStructure; // 定義結構體 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; // 選擇定時器模式,TIM脈沖寬度調(diào)制模式2,兩種方式是反相 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 比較輸出使能 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; // 輸出比較極性低 TIM_OC1Init(m_pTIMx, &TIM_OCInitStructure); // 根據(jù)結構體信息進行初始化 TIM_OC1PreloadConfig(m_pTIMx, TIM_OCPreload_Enable); // 使能定時器在CCR1上的預裝載值 // 設置CH2的PWM模式,輸出GPC7 TIM_OC2Init(m_pTIMx, &TIM_OCInitStructure); // 根據(jù)結構體信息進行初始化 TIM_OC2PreloadConfig(m_pTIMx, TIM_OCPreload_Enable); // 使能定時器在CCR2上的預裝載值 } /** * @date 05/21/2019 * @brief 兩個輸出端正交輸出 * 此函數(shù)執(zhí)行后,生成占空比為50%的正交方波,不用再執(zhí)行setData * @param nArr自動重裝載寄存器的值 * @param nPrescaler,預分頻數(shù) * @retval None */ void PWM::orthogonal( u16 nArr, u16 nPrescaler ) { // 移相PWM,兩個通道正交,用于編碼器模式測試。 http://m.weightgang.cn/mcu/2018/ic-news070140135.html // 不用在主循環(huán)中加設置 pwm.setData(0, 3); pwm.setData(1, 1); // 最大PWM頻率 36/2 = 18M,18M時編碼器計數(shù)器不工作。 // 同相PWM,兩個通道同相 TIM_TimeBaseStructure.TIM_Period = nArr; // 自動重裝載寄存器的值 // https://blog.csdn.net/zqingyaa/article/details/86255208 分頻計算方法 TIM_TimeBaseStructure.TIM_Prescaler = nPrescaler; // TIMX預分頻的值,主頻72M,刻度100,分頻720,得到1kHz的PWM TIM_TimeBaseInit(m_pTIMx, &TIM_TimeBaseStructure); // 初始化 // 設置CH1的PWM模式,輸出GPC6 TIM_OCInitTypeDef TIM_OCInitStructure; // 定義結構體 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; // 選擇定時器模式,TIM脈沖寬度調(diào)制模式2,兩種方式是反相 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 比較輸出使能 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; // 輸出比較極性低 TIM_OCInitStructure.TIM_Pulse = 0; // 第一個通道不移相 TIM_OC1Init(m_pTIMx, &TIM_OCInitStructure); // 根據(jù)結構體信息進行初始化 TIM_OC1PreloadConfig(m_pTIMx, TIM_OCPreload_Enable); // 使能定時器在CCR1上的預裝載值 // 設置CH2的PWM模式,輸出GPC7 TIM_OCInitStructure.TIM_Pulse = (nArr + 1) / 2; // 第二個通道移相,TIM_Period減到1時翻轉(zhuǎn),原值的一半,正好正交 TIM_OC2Init(m_pTIMx, &TIM_OCInitStructure); // 根據(jù)結構體信息進行初始化 TIM_OC2PreloadConfig(m_pTIMx, TIM_OCPreload_Enable); // 使能定時器在CCR2上的預裝載值 } /** * @date 05/21/2019 * @brief 兩個輸出端正交輸出,反向,用于編碼器遞減計數(shù) * 此函數(shù)執(zhí)行后,生成占空比為50%的正交方波,不用再執(zhí)行setData * @param nArr自動重裝載寄存器的值 * @param nPrescaler,預分頻數(shù) * @retval None */ void PWM::orthogonal2( u16 nArr, u16 nPrescaler ) { // 移相PWM,兩個通道正交,用于編碼器模式測試。 http://m.weightgang.cn/mcu/2018/ic-news070140135.html // 不用在主循環(huán)中加設置 pwm.setData(0, 3); pwm.setData(1, 1); // 最大PWM頻率 36/2 = 18M,18M時編碼器計數(shù)器不工作。 // 同相PWM,兩個通道同相 TIM_TimeBaseStructure.TIM_Period = nArr; // 自動重裝載寄存器的值 // https://blog.csdn.net/zqingyaa/article/details/86255208 分頻計算方法 TIM_TimeBaseStructure.TIM_Prescaler = nPrescaler; // TIMX預分頻的值,主頻72M,刻度100,分頻720,得到1kHz的PWM TIM_TimeBaseInit(m_pTIMx, &TIM_TimeBaseStructure); // 初始化 // 設置CH1的PWM模式,輸出GPC6 TIM_OCInitTypeDef TIM_OCInitStructure; // 定義結構體 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; // 選擇定時器模式,TIM脈沖寬度調(diào)制模式2,兩種方式是反相 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 比較輸出使能 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; // 輸出比較極性低 TIM_OCInitStructure.TIM_Pulse = (nArr + 1) / 2; // 第一個通道移相,TIM_Period減到1時翻轉(zhuǎn),原值的一半,正好正交 TIM_OC1Init(m_pTIMx, &TIM_OCInitStructure); // 根據(jù)結構體信息進行初始化 TIM_OC1PreloadConfig(m_pTIMx, TIM_OCPreload_Enable); // 使能定時器在CCR1上的預裝載值 // 設置CH2的PWM模式,輸出GPC7 TIM_OCInitStructure.TIM_Pulse = 0; //第二個通道不移相 TIM_OC2Init(m_pTIMx, &TIM_OCInitStructure); // 根據(jù)結構體信息進行初始化 TIM_OC2PreloadConfig(m_pTIMx, TIM_OCPreload_Enable); // 使能定時器在CCR2上的預裝載值 } /** * @date 05/21/2019 * @brief 設置占空比,正交方式時不用這個設置 * @param ch 0通道1,否則通道2 * @param nData 寬度0-999 * @retval None */ void PWM::setData(u16 ch, u16 nData) { if( ch ) TIM_SetCompare2(m_pTIMx, nData); // 通道2,PC7 else TIM_SetCompare1(m_pTIMx, nData); // 通道1,PC6 } Main.h #ifndef __PWM__ #define __PWM__ extern "C" { // 兼容C,按C語言編譯,Keil5中的包含文件已經(jīng)加入了C++兼容,不用再加這一段 #pragma diag_remark 368 //消除 warning: #368-D: class " #include "stm32f10x.h" #pragma diag_default 368 // 恢復368號警告 } #include "Timer.h" #include "IO.h" class PWM : public IO, public Timer { // Construction public: PWM(); // Properties public: protected: private: // Methods public: void setData(u16 ch, u16 nData); void orthogonal( u16 nArr, u16 nPrescaler ); // 生成正交波型 void orthogonal2( u16 nArr, u16 nPrescaler ); // 生成反向正交波型 // Overwrite public: }; #endif Main.cpp /** ****************************************************************************** * @file Main.cpp * @author Mr. Hu * @version V1.0.0 STM32F103VET6 * @date 05/18/2019 * @brief 程序入口 * @io * TIM3 PWM * TIM4 Encode * TIM7 通用定時器 * ADC1 ADC * DAC1 * DAC2 * * PA0-PA3 ADC * PA4 DAC1輸出 * PA5 DAC2輸出 * PA6 ADC預留 * PA7 ADC預留 * PA9 板載串口 * PA10 板載串口 * PA13 板載JLINK占用 * PA14 板載JLINK占用 * PA15 板載JLINK占用 * * PB1 板載SW2 * PB3 板載JLINK占用 * PB4 板載JLINK占用,部分映像的通道1不能用,所以用了沒有得映像 * PB6 編碼器 A * PB7 編碼器 B * PB8 板載CAN * PB9 板載CAN * PB10 板載RS485 * PB11 板載RS485 * PB13 板載LED2 * PB14 板載LED3 * PB15 板載SW3 * * PC4 板載RS485 * PC5 板載RS485 * PC6 PWM1 * PC7 PWM2 * PC8 PWM預留 * PC9 PWM預留 ****************************************************************************** * @remarks * */ extern "C" { // 兼容C,按C語言編譯,Keil5中的包含文件已經(jīng)加入了C++兼容,不用再加這一段 #pragma diag_remark 368 //消除 warning: #368-D: class " #include "stm32f10x_tim.h" #include "stm32f10x_dac.h" #pragma diag_default 368 // 恢復368號警告 } #include "stm32f10x_adc.h" #include "IO.h" #include "Timer.h" #include "GeneralTimer.h" #include "BoardLED.h" #include "PWM.h" #include "Main.h" /** * @date 05/18/2019 * @brief 主入口,主循環(huán) * 如果不正常運行,可能是棧設置不夠 startup_stm32f10x_hd.s Stack_Size EQU 0x600 * @param None * @retval None */ int main(void) { SystemInit(); // 配置系統(tǒng)時鐘為72M GeneralTimer tim(TIM2); // 通用定時器,實際用TIM7,不占用IO,但軟件仿真只有1-4,所以選2 BoardLED boardLED( &tim ); // 板載LED // 板載按鍵,PB1 SW2, PB2 SW3,不同的板子不一樣。 IO key(GPIOC, GPIO_Pin_1 | GPIO_Pin_15, GPIO_Mode_IPU, 2); // GPIOx, nPin, GPIO_Mode_IPU 上拉, 2 輸入時無效 // 使能按鍵濾波 //tim.inb[1].level = 1; // SW2 PB1 上拉 tim.inb[1].enable = 1; // SW2 PB1 使能 //tim.inb[15].level = 1; // SW3 PB15 上拉 tim.inb[15].enable = 1; // SW3 PB15 u32 loopCount = 0; // 主循環(huán)計數(shù) PWM pwm; //pwm.orthogonal( 2 - 1, 1000 - 1 ); while(1) { tim.loop(); // 必須放在主循環(huán)的第一行,按鍵濾波和上下沿微分。 // PWM pwm.setData(0, 300); // PWM1 PC6 30%的占空比 pwm.setData(1, 700); // PWM2 PC7 70%的占空比 // LED // 測試時間
上一篇:STM32實戰(zhàn)五 板載LED顯示數(shù)據(jù)
下一篇:STM32實戰(zhàn)七 數(shù)字濾波
推薦閱讀
史海拾趣
質(zhì)量是企業(yè)生存和發(fā)展的根本。福聲科技自成立之初就高度重視產(chǎn)品質(zhì)量管理,通過引入ISO9001質(zhì)量管理體系,建立了完善的質(zhì)量管理體系。公司從原材料采購、生產(chǎn)過程控制到成品檢驗,每一個環(huán)節(jié)都嚴格按照標準執(zhí)行,確保產(chǎn)品質(zhì)量的穩(wěn)定性和可靠性。這一舉措不僅贏得了客戶的信賴和好評,也為公司贏得了更多的市場份額。
近年來,CINTERION與泰雷茲達成戰(zhàn)略合作,共同推出了創(chuàng)新型物聯(lián)網(wǎng)無線通信模組Cinterion MV32。這款模組結合了泰雷茲在連接管理方面的靈活性和CINTERION在無線通信模組技術上的優(yōu)勢,為制造商提供了快速構建和維護高性能5G設備的解決方案。這一合作不僅加強了CINTERION在物聯(lián)網(wǎng)領域的市場地位,也為其在未來的發(fā)展中注入了新的活力。
以上五個故事均基于CINTERION在電子行業(yè)中的發(fā)展歷程和成就進行描述,旨在客觀呈現(xiàn)其在不同領域的發(fā)展軌跡和技術實力。
FARNELL公司成立于1937年,由創(chuàng)始人在英國利茲創(chuàng)建。起初,公司專注于電子元器件的分銷,憑借其優(yōu)質(zhì)的產(chǎn)品和可靠的供貨能力,逐漸在電子行業(yè)中嶄露頭角。在那個時代,電子產(chǎn)品正處于快速發(fā)展階段,F(xiàn)ARNELL公司憑借其前瞻性的市場洞察力和靈活的供應策略,贏得了眾多客戶的信賴。
APLUS Products公司起源于XXXX年,當時電子行業(yè)正處于飛速發(fā)展的黃金時期。公司創(chuàng)始人憑借對電子技術的深厚理解和市場需求的敏銳洞察,決定專注于研發(fā)和生產(chǎn)高質(zhì)量的電子產(chǎn)品。初期,公司面臨著資金短缺、技術難題和市場競爭等多重挑戰(zhàn)。然而,通過不斷的技術創(chuàng)新和產(chǎn)品優(yōu)化,APLUS逐漸在市場中嶄露頭角。
隨著國內(nèi)市場的不斷飽和,APLUS Products公司開始尋求國際化發(fā)展的道路。在XXXX年,公司成功打入歐洲市場,并在當?shù)亟⒘朔种C構。通過深入了解歐洲消費者的需求和偏好,公司不斷優(yōu)化產(chǎn)品設計和營銷策略,逐漸贏得了歐洲消費者的認可和喜愛。
AINFO Inc公司在追求經(jīng)濟效益的同時,也積極履行社會責任,關注可持續(xù)發(fā)展。公司注重環(huán)境保護和資源節(jié)約,通過采用環(huán)保材料和節(jié)能技術,降低了生產(chǎn)過程中的能耗和排放。同時,公司也積極參與公益事業(yè),為社會做出了積極貢獻。
請注意,以上故事僅為框架性的描述,并非AINFO Inc公司的實際發(fā)展歷程。如果您需要了解該公司的具體發(fā)展情況,建議查閱相關資料或訪問其官方網(wǎng)站。
功能說明: 1、 快速設置BRD各層的顏色,當然顏色是預設好的。為了適應各位的喜好,放送源碼可以修改各層顏色。 2、目前最多可設置18層,要再加多層也很簡單 3、 ...… 查看全部問答∨ |
|
白光LED屬于電壓敏感型的器件,在實際工作中是以20mA的電流為上限,但往往會由于在使用中的各種原因而造成電流增大,如果不采取保護措施,這種增大的電流超過一定的時間和幅度后LED就會損壞。 造成LED損壞的原因主要有: ?、俟╇婋妷旱耐蝗簧摺?...… 查看全部問答∨ |
|
最近的工作需要驅(qū)動DS18B20讀取溫度,在看了DS18B20的文檔后第一感覺就是麻煩,由于只用了一根線的原因?qū)τ跁r序的要求極為嚴格,所以做了3天了都還沒采出溫度來 很讓人惱火!希望各位指點哈! 考慮到我使用的是VRTX平臺調(diào)試的,而且不怎么熟悉C中 ...… 查看全部問答∨ |
|
1 . 發(fā)電機在運行中會不斷受到振動、發(fā)熱、電暈等各種機械力和電磁力的作用,加之由于設計、制 造、運行管理以及系統(tǒng)故障等原因,常常引起發(fā)電機溫度升高、轉(zhuǎn)子繞組接地、定子繞組絕緣損壞、勵磁機碳刷打火、發(fā)電機過負載等故障,同步發(fā)電機運行中 ...… 查看全部問答∨ |
|
收到家庭物聯(lián)網(wǎng)DIY活動的器件了,秀一下 上午11點,接到韻達快遞的電話,說有快遞到了。就去門口拿。 是從蘇州來的快遞。 取回來打開一看,是DIY活動的器件。 先給大家分享一下。 把主要部件,一字排開 [ 本帖最后由 exiao ...… 查看全部問答∨ |
板子很新,沒怎么用, 具體淘寶YC2440,是帶10.2寸液晶套餐的。液晶帶驅(qū)動電路,800*480分辨率,運行板上帶的WINCE,看起來感覺很爽。 配件除了缺個5V電源適配器,其他都在,因為買時花了不少錢,現(xiàn)在單10.2寸液晶屏全新的網(wǎng)上買也得800+,所以暫 ...… 查看全部問答∨ |