1.認識PWM
PWM(Pulse Width Modulation脈寬調制)是利用微處理器的數字輸出來對模擬電路進行控制的一種非常有效的技術。PWM是一種對模擬信號電平進行數字編碼的方法。通過高分辨率計數器的使用,方波占空比被調制用來對一個具體模擬信號的電平進行編碼。PWM信號任然是數字的,因為在給定的任何時刻,滿幅值的直流供電要么完全有,要么完全無。比如我們的電壓輸出是5v的,那么經過改變PWM的占空比,可以達到在一定時間內輸出3.3V或者1.3V的效果
2.CW32 PWM介紹
普通的IO控制雖然能讓電機實現正反轉但是電機只能在一個固定的速度下實現,我們沒法改變電機轉動的速度,那在實際使用中是非常不方便的,所以本項目的目的為實現開發板上電機調速。
想要實現電機調速其實非常簡單,根據前文芯片手冊可知,控制引腳置一個置高電平一個置低電平電機即可動起來,兩個都置低電平或高電平就會停止,那我們只需要改變高電平持續時間不就可以實現調速了嗎。想要改變高電平持續時間,我們可以使用 CW32內部的硬件資源PWM。
PWM功能是在定時器的基礎上實現的,但不是所有的定時器都支持PWM輸出功能。從用戶手冊上可以了解到,高級定時器擁有4個PWM通道,通用定時器擁有4個PWM通道,通用定時器擁有PWM通道。每一個PWM通道都對應單片機的一個管腳,這個引腳不是唯一固定的,可能有一個或者兩個管腳都對應同一個通道,我們在使用的時候可以任選其一進行配置。
根據開發板原理圖可知,在開發板上左右兩個電機分別接到了兩塊RZ7899上,左電機為PB3和PB4,右電機為PB1和PB5。再翻閱CW32數據手冊可知

PB4和PB5復用功能可以使用通用定時器輸出比較的一通道和二通道,我們配置一下即可。
3.PWM基本參數
PWM是脈沖寬度調制,具有兩個非常重要的參數:頻率和占空比。
- 頻率:PWM的頻率是整個周期的倒數。
- 占空比:占空比是指一個周期內高電平所占的比例。
4.控制方法
采樣控制理論中有一個重要結論:沖量相等而形狀不同的窄脈沖加在具有慣性的環節上時,其效果基本相同。PWM控制技術就是以該結論為理論基礎,對半導體開關器件的導通和關斷進行控制,使輸出端得到一系列幅值相等而寬度不相等的脈沖,用這些脈沖來代替正弦波或其他所需要的波形。按一定的規則對各脈沖的寬度進行調制,即可改變逆變電路輸出電壓的大小,也可改變輸出頻率。
5.基本原理
控制方式就是對逆變電路開關器件的通斷進行控制,使輸出端得到一系列幅值相等但寬度不一致的脈沖,用這些脈沖來代替正弦波或所需要的波形。也就是在輸出波形的半個周期中產生多個脈沖,使個脈沖的等值電壓為正弦波形,所獲得的輸出平滑且低次諧波少。按一定的規則對各脈沖的寬度進行調制,即可改變逆變電路輸出電壓的大小,也可改變輸出頻率。
6.PWM優點
PWM的一個優點是從處理器到被控制系統信號都是數字形式,無需進行數模轉換。讓信號保持為數字形式可將噪聲影響降到最小。噪聲只有在強到足以將邏輯1改變為邏輯0或將邏輯0改變為邏輯1時,才能對數字信號產生影響。對噪聲抵抗能力的增強是PWM相對于模擬控制的另一個優點,而且這也是在某些時候將PWM用于通信的主要原因。
7.配置流程
一般使用定時器PWM功能,都需要有以下幾個步驟。
8.配置GPIO
前面介紹過PWM輸出是依賴于定時器的,所以要對定時器進行配置,但是我們不使用定時器的中斷功能,顧不用對定時器的中斷進行配置。
又因為我們使用的PB4是GTIM1的通道1,PB5是GTIM1的通道2,所以我們要配置PB0的GPIO參數。
首先是GPIO的參數結構體:
GPIO_InitTypeDef GPIO_InitStruct; // GPIO初始化結構體
然后是GPIO配置參數:
GPIO_Initstructure.IT=GPIO_IT_NONE;
GPIO_Initstructure.Mode=GPIO_MODE_OUTPUT_PP;//推挽輸出
GPIO_Initstructure.Pins=GPIO_PIN_4 | GPIO_PIN_5;//引腳配置
GPIO_Initstructure.Speed=GPIO_SPEED_HIGH;
GPIO_Init(CW_GPIOB,&GPIO_Initstructure);
使用復用功能,將PB5復用為GTIM1通道2的通道,將PB4復用為GTIM1通道1的通道:
PB04_AFx_GTIM1CH1();//配置PB4復用功能為通用定時器一的一通道
PB05_AFx_GTIM1CH2();//配置PB5復用功能為通用定時器一的二通道
9.配置定時器
要使用定時器參數配置有一個結構體,如圖所示。

參數說明
-
uint32_t Mode: 這個字段用于指定GTIM的工作模式。
- GTIM_MODE_TIME:基本定時器模式。
- GTIM_MODE_COUNTER:計數器模式。
- GTIM_MODE_TRIGGER:觸發模式,可能指定時器被用作觸發源或響應于某個外部觸發信號開始/停止計數。
- GTIM_MODE_GATE:門控模式,意味著定時器的計數操作受一個外部信號的控制,即只有當這個控制信號有效時,定時器才開始或繼續計數。
- uint32_t OneShotMode: 此字段決定定時器是工作在單次計數模式還是一直循環計數(連續計數)模式。如果設置為單次模式,定時器在達到重載值后會停止計數,直到復位或重新配置;如果是連續計數模式,則會在達到重載值后自動重置并繼續計數。
- FunctionalState ToggleOutState: 這個字段用于控制定時器的輸出翻轉功能是否使能。FunctionalState是一個類型定義,通常有兩個的值:ENABLE和DISABLE,分別表示啟用或禁用定時器的輸出引腳翻轉功能。當定時器計數達到特定條件時,其關聯的輸出引腳電平會翻轉。
- uint32_t Prescaler: 預分頻器的設置值。預分頻器用于降低提供給定時器時鐘的頻率,使得計數速度變慢,從而實現更寬范圍的計時能力。
-
uint32_t ReloadValue: 重載值,也稱為自動裝載寄存器值。當計數值達到此值時,定時器會產生一個更新事件(如中斷或DMA請求),并且計數器會根據OneShotMode的設置重置或繼續計數。這個值決定了定時器溢出的周期,是定時操作的核心配置之一。
結構體定義:
GTIM_InitTypeDef GTIM_InitStruct; // 通用定時器初始化結構體
相關配置如下:
GTIM_InitStruct.Mode = GTIM_MODE_TIME; // 定時器模式
GTIM_InitStruct.OneShotMode = GTIM_COUNT_CONTINUE; // 連續計數模式
GTIM_InitStruct.Prescaler = GTIM_PRESCALER_DIV1024; // DCLK = PCLK / 64 = 64MHz/64 = 1MHz
GTIM_InitStruct.ReloadValue = 1000; // 重裝載值設置
GTIM_InitStruct.ToggleOutState = DISABLE; // 輸出翻轉功能
初始化配置:
GTIM_TimeBaseInit(CW_GTIM1, >IM_InitStruct); // 初始化
10.配置PWM
配置好GTIMER1參數之后,需要配置PWM輸出。
GTIM_OCInit(CW_GTIM1,GTIM_CHANNEL1,GTIM_OC_OUTPUT_PWM_HIGH);//輸出比較通道初始化
GTIM_OCInit(CW_GTIM1,GTIM_CHANNEL2,GTIM_OC_OUTPUT_PWM_HIGH);
11.使能TIMER
我們使用函數TIM_Cmd初始化函數:
GTIM_Cmd(CW_GTIM1, ENABLE); // 使能定時器
12.調整定時器輸出通道占空比
void GTIM_SetCompare1(GTIM_TypeDef *GTIMx, uint32_t Value)
該函數GTIM_SetCompare3用于設置通用定時器(GTIM)的第3個通道(Channel 3)的比較值(Compare Value)
- GTIMx: 指向通用定時器的類型定義指針。這是一個重要的參數,用來指定要操作的具體定時器實例(例如 TIM1、TIM2 等)。使用前需要確保指針非空且指向有效的定時器。
- Value: 要設置的比較值,類型為無符號32位整數。這個值決定了定時器計數器何時與之“比較”,進而可能觸發輸出狀態的改變(比如在PWM模式下改變占空比)
函數沒有返回值(@retval None)。
注意:每個通道有不同的函數。通道2是GTIM_SetCompare2,通道3是GTIM_SetCompare3,如此以此類推。。。。
在PWM(脈沖寬度調制)應用中,可以通過改變CCR3的值來調整PWM信號的占空比。例如,增加CCR3的值會增加PWM高電平的持續時間,從而增加占空比。
13.軟件編寫
修改代碼如下:
void Motor_Init(void)
{
RCC_AHBPeriphClk_Enable(RCC_AHB_PERIPH_GPIOB,ENABLE);//開啟GPIOB時鐘
RCC_APBPeriphClk_Enable1(RCC_APB1_PERIPH_GTIM1,ENABLE);//開啟通用定時器一時鐘
PB04_AFx_GTIM1CH1();//配置PB4復用功能為通用定時器一的一通道
PB05_AFx_GTIM1CH2();//配置PB5復用功能為通用定時器一的二通道
GPIO_InitTypeDef GPIO_Initstructure;
GPIO_Initstructure.IT=GPIO_IT_NONE;
GPIO_Initstructure.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_Initstructure.Pins=GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_3 | GPIO_PIN_1;
GPIO_Initstructure.Speed=GPIO_SPEED_HIGH;
GPIO_Init(CW_GPIOB,&GPIO_Initstructure);
GTIM_InitTypeDef GTIM_Initstructure;
GTIM_Initstructure.Mode=GTIM_MODE_TIME;//定時器模式
GTIM_Initstructure.OneShotMode=GTIM_COUNT_CONTINUE;//連續計數
GTIM_Initstructure.Prescaler=GTIM_PRESCALER_DIV1024;//配置預分頻器
GTIM_Initstructure.ReloadValue=1000;//自動重裝載值
GTIM_Initstructure.ToggleOutState=DISABLE;//關閉輸出反轉
GTIM_TimeBaseInit(CW_GTIM1,>IM_Initstructure);
GTIM_OCInit(CW_GTIM1,GTIM_CHANNEL1,GTIM_OC_OUTPUT_PWM_HIGH);//輸出比較通道初始化
GTIM_OCInit(CW_GTIM1,GTIM_CHANNEL2,GTIM_OC_OUTPUT_PWM_HIGH);
CW_GTIM1->CCR1=0;//初始化ccr
CW_GTIM1->CCR2=0;
GTIM_ITConfig(CW_GTIM1,GTIM_IT_OV,ENABLE);
GTIM_Cmd(CW_GTIM1,ENABLE);
}
配置輸出通道
/**************************
通道一輸出配置
形參:占空比,最大1000
**************************/
void GTIM1_SetCompare1(uint16_t value)//通道一輸出配置
{
GTIM_SetCompare1(CW_GTIM1,value);
}
/**************************
通道二輸出配置
形參:占空比,最大1000
**************************/
void GTIM1_SetCompare2(uint16_t value)//通道二輸出配置
{
GTIM_SetCompare2(CW_GTIM1,value);
}
電機正反轉
/**************************
//左電機正轉
形參:占空比,最大1000
**************************/
void Motor_Left_Run(uint16_t value)//左電機正轉
{
GTIM1_SetCompare1(value);
PB03_SETHIGH();
}
/**************************
//右電機正轉
形參:占空比,最大1000
**************************/
void Motor_Right_Retreat(uint16_t value)//右電機反轉
{
value=1000-value;
GTIM1_SetCompare2(value);
PB12_SETLOW();
}
/**************************
左電機反轉
形參:占空比,最大1000
**************************/
void Motor_Left_Retreat(uint16_t value)//左電機反轉
{
value=1000-value;
GTIM1_SetCompare1(value);
PB03_SETLOW();
}
/**************************
右電機正轉
形參:占空比,最大1000
**************************/
void Motor_Right_Run(uint16_t value)//右電機正轉
{
GTIM1_SetCompare2(value);
PB12_SETHIGH();
}
void Car_Run(uint16_t value)//小車前進
{
Motor_Left_Run(value);
Motor_Right_Run(value);
}
void Car_Left(uint16_t value)//左轉
{
Motor_Left_Retreat(value);
Motor_Right_Run(value);
}
void Car_Right(uint16_t value)//右轉
{
Motor_Left_Run(value);
Motor_Right_Retreat(value);
}
void Car_Retreat(uint16_t value)//后退
{
Motor_Left_Retreat(value);
Motor_Right_Retreat(value);
}
void Car_Stop(void)//停止
{
Motor_Left_Run(0);
Motor_Right_Run(0);
}
在主函數中編寫以下代碼
int16_t keynum,speed;
int main(void)
{
OLED_Init();//初始化
LED_Init();//LED初始化
Key_Init();//按鍵初始化
Motor_Init();//初始化電機
while(1)
{
keynum=Key();//獲取鍵碼,
if(keynum==1){speed+=100;if(speed>1000){speed=1000;}}
if(keynum==2){speed-=100;if(speed0){speed=0;}}
Motor_Left_Run(speed);//控制左電機
Motor_Right_Run(speed);//控制右電機
OLED_ShowString(1,1,"speed=");
OLED_ShowNum(1,7,speed,4);//屏幕顯示變量
}
}
14.實驗現象
將本次實驗代碼燒錄進開發板之后,我們可以觀察到以下現象:
- 按下按鍵一,電機速度將會以10%的速度遞增
- 按下按鍵二,電機速度將會以10%的速度遞減
- 屏幕顯示當前占空比
-
PWM
+關注
關注
116文章
5880瀏覽量
226200 -
智能小車
+關注
關注
87文章
565瀏覽量
83495 -
CW32
+關注
關注
1文章
323瀏覽量
1924
發布評論請先 登錄
CW32L012/F030靈眸X1智能小車——板載WS2812驅動示例
CW32L012/F030靈眸X1智能小車——超聲波模塊配置
CW32L012/F030靈眸X1智能小車——使用藍牙模塊通訊
堅持繼續布局32位MCU,進一步完善產品陣容,96Mhz主頻CW32L012新品發布!
**CW32L012****開發評估板的第一個程序**
CW32L012小型機器人控制評估板活動 四足機器人+智能小車 開箱評測
CW32F030C8T7永磁同步電機無感FOC控制的方案
使用芯源CW32的CW32L012開發評估板做了spi屏幕驅動
CW32L012與STM32F103的三角運算性能對比
CW32L012與STM32G431的CORDIC三角函數運算性能對比
CW32L012/F030靈眸X1智能小車--電機調速控制
評論