天九接收機訊號 ppm pwm 學習過程
阿新 • • 發佈:2019-01-26
ppm和pcm是訊號傳輸的一種編碼格式。
pwm是對負載進行平均功率控制的一種方式(電子設計的都應該知道電機pwm的控制原理)。
那麼模型遙控接收機輸出的脈衝訊號是pwm訊號嗎?很多人都認為是pwm訊號。其實不然。如果簡單的看確實是pwm。但你要是把這個訊號當作pwm訊號來設計個電調或舵機等模型外設,就有可能出現相容問題。因為模型接收機輸出的訊號嚴謹的部分是脈衝的寬度,而週期是不嚴謹的,各個廠家的訊號週期都有差別,甚至對於一個接收機在操作時週期是變化的。也就是說週期不確定的,去談佔空比就會有問題了。(這也是我自己寫了stm32pwm輸入捕捉的程式結果測試自己產生的pwm週期佔空比都對 都是測試天9時就週期啊佔空比啊一直在邊的原因)。
在寫輸入捕捉時要注意輸入捕獲的TIMER的基準時鐘和最大計數,和中斷函式裡的計算公式就可以了。基準時鐘跟計算週期有關,最大計數和你能捕捉的最低頻率有關。 void Timer2_Input(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
SystemInit();
/* TIM2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/* GPIOA clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 0xffff; //最大計數為65535,週期最長65535us即頻率最低15hz
TIM_TimeBaseStructure.TIM_Prescaler = (72000000/1000000)-1; //基準時鐘為1000000hz,也就是說你的計數週期是1us
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);//
/* Enable the TIM2 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* NVIC configuration */
/* TIM2 channel 2 pin (PA.01) configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* TIM2 configuration: PWM Input mode ------------------------
The external signal is connected to TIM2 CH2 pin (PA.01),
The Rising edge is used as active edge,
The TIM2 CCR2 is used to compute the frequency value
The TIM2 CCR1 is used to compute the duty cycle value
------------------------------------------------------------ */
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_PWMIConfig(TIM2, &TIM_ICInitStructure);
/* Select the TIM2 Input Trigger: TI2FP2 */
TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);
/* Select the slave Mode: Reset Mode */
TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);
/* Enable the Master/Slave Mode */
TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);
/* TIM enable counter */
TIM_Cmd(TIM2, ENABLE);
/* Enable the CC2 Interrupt Request */
TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);
}
中斷函式如下void TIM2_IRQHandler(void)
{
// Clear TIM2 Capture compare interrupt pending bit //
TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
// Get the Input Capture value //
IC2Value = TIM_GetCapture2(TIM2);
if (IC2Value != 0)
{
// Duty cycle computation //
DutyCycle = (TIM_GetCapture1(TIM2) * 100) / IC2Value;
// Frequency computation //
Frequency = 1000000/ IC2Value; //這裡1000000就要和上邊保持一致就可以
}
else
{
DutyCycle = 0;
Frequency = 0;
}
}
pwm是對負載進行平均功率控制的一種方式(電子設計的都應該知道電機pwm的控制原理)。
那麼模型遙控接收機輸出的脈衝訊號是pwm訊號嗎?很多人都認為是pwm訊號。其實不然。如果簡單的看確實是pwm。但你要是把這個訊號當作pwm訊號來設計個電調或舵機等模型外設,就有可能出現相容問題。因為模型接收機輸出的訊號嚴謹的部分是脈衝的寬度,而週期是不嚴謹的,各個廠家的訊號週期都有差別,甚至對於一個接收機在操作時週期是變化的。也就是說週期不確定的,去談佔空比就會有問題了。(這也是我自己寫了stm32pwm輸入捕捉的程式結果測試自己產生的pwm週期佔空比都對 都是測試天9時就週期啊佔空比啊一直在邊的原因)。
所以不提倡把模型接收機輸出訊號說成pwm訊號。以免造成誤解。
這裡把自己除錯 固定佔空比pwm的輸入捕捉理解寫下來,害怕以後再做時又不知道這次怎麼搞的了。捕獲原理:1. 每個定時器有四個輸入捕獲通道IC1、IC2、IC3、IC4。且IC1 IC2一組,IC3 IC4一組。並且可是設定管腳和暫存器的對應關係。
2. 同一個TIx輸入映射了兩個ICx訊號。
3. 這兩個ICx訊號分別在相反的極性邊沿有效。
4. 兩個邊沿訊號中的一個被選為觸發訊號,並且從模式控制器被設定成復位模式。
5. 當觸發訊號來臨時,被設定成觸發輸入訊號的捕獲暫存器,捕獲“一個PWM週期(即連續的兩個上升沿或下降沿)”,它等於包含TIM時鐘週期的個數(即捕獲暫存器中捕獲的為TIM的計數個數n)。
6. 同樣另一個捕獲通道捕獲觸發訊號和下一個相反極性的邊沿訊號的計數個數m,即(即高電平的週期或低電平的週期)
7. 由此可以計算出PWM的時鐘週期和佔空比了
frequency=f(TIM時鐘頻率)/n。
duty cycle=(高電平計數個數/n),
若m為高電平計數個數,則duty cycle=m/n
若m為低電平計數個數,則duty cycle=(n-m)/n
注:因為計數器為16位,所以一個週期最多計數65535個,所以測得的 最小頻率= TIM時鐘頻率/65535。
在寫輸入捕捉時要注意輸入捕獲的TIMER的基準時鐘和最大計數,和中斷函式裡的計算公式就可以了。基準時鐘跟計算週期有關,最大計數和你能捕捉的最低頻率有關。
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
SystemInit();
/* TIM2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/* GPIOA clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 0xffff; //最大計數為65535,週期最長65535us即頻率最低15hz
TIM_TimeBaseStructure.TIM_Prescaler = (72000000/1000000)-1; //基準時鐘為1000000hz,也就是說你的計數週期是1us
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);//
/* Enable the TIM2 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* NVIC configuration */
/* TIM2 channel 2 pin (PA.01) configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* TIM2 configuration: PWM Input mode ------------------------
The external signal is connected to TIM2 CH2 pin (PA.01),
The Rising edge is used as active edge,
The TIM2 CCR2 is used to compute the frequency value
The TIM2 CCR1 is used to compute the duty cycle value
------------------------------------------------------------ */
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_PWMIConfig(TIM2, &TIM_ICInitStructure);
/* Select the TIM2 Input Trigger: TI2FP2 */
TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);
/* Select the slave Mode: Reset Mode */
TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);
/* Enable the Master/Slave Mode */
TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);
/* TIM enable counter */
TIM_Cmd(TIM2, ENABLE);
/* Enable the CC2 Interrupt Request */
TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);
}
中斷函式如下void TIM2_IRQHandler(void)
{
// Clear TIM2 Capture compare interrupt pending bit //
TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
// Get the Input Capture value //
IC2Value = TIM_GetCapture2(TIM2);
if (IC2Value != 0)
{
// Duty cycle computation //
DutyCycle = (TIM_GetCapture1(TIM2) * 100) / IC2Value;
// Frequency computation //
Frequency = 1000000/ IC2Value; //這裡1000000就要和上邊保持一致就可以
}
else
{
DutyCycle = 0;
Frequency = 0;
}
}