久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6131|回復: 1
打印 上一主題 下一主題
收起左側

通過上位機輸入產生PWM控制LED燈實驗

[復制鏈接]
跳轉到指定樓層
樓主
ID:231047 發表于 2017-9-5 09:45 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
1        實驗目的
上位機通過串口發送格式為:“redbrightness,greenbrightness,bluebrightness”的字符串到MCU。MCU將數字轉化成相應的亮度。
2        實驗總體設計
實驗主要分兩個部分:PWM配置以及串口通信配置。整個實驗的難點在于ASCII碼轉換為數字的過程。
3        PWM產生原理
通用定時器可以利用GPIO引腳進行脈沖輸出。要使STM32的通用定時器TIMx產生PWM輸出,需要用到3個寄存器。分別是:捕獲/比較模式寄存器(TIMx_CCMR1/2)、捕獲/比較使能寄存器(TIMx_CCER)、捕獲/比較寄存器(TIMx_CCR1~4)。(注意,還有個TIMx的ARR寄存器是用來控制pwm的輸出頻率)。
對于捕獲/比較模式寄存器(TIMx_CCMR1/2),該寄存器總共有2個,TIMx _CCMR1和TIMx_CCMR2。TIMx_CCMR1控制CH1和2,而TIMx_CCMR2控制CH3和4。
其次是捕獲/比較使能寄存器(TIMx_CCER),該寄存器控制著各個輸入輸出通道的開關。
最后是捕獲/比較寄存器(TIMx_CCR1~4),該寄存器總共有4個,對應4個輸通道CH1~4。4個寄存器作用相近,都是用來設置pwm的占空比的。
例如,若配置脈沖計數器TIMx_CNT為向上計數,而重載寄存器TIMx_ARR被配置為N,即TIMx_CNT的當前計數值數值X在TIMxCLK時鐘源的驅動下不斷累加,當TIMx_CNT的數值X大于N時,會重置TIMx_CNT數值為0重新計數。
而在TIMxCNT計數的同時,TIMxCNT的計數值X會與比較寄存器TIMx_CCR預先存儲了的數值A進行比較,當脈沖計數器TIMx_CNT的數值X小于比較寄存器TIMx_CCR的值A時,輸出高電平(或低電平),相反地,當脈沖計數器的數值X大于或等于比較寄存器的值A時,輸出低電平(或高電平)。
如此循環,得到的輸出脈沖周期就為重載寄存器TIMx_ARR存儲的數值(N+1)乘以觸發脈沖的時鐘周期,其脈沖寬度則為比較寄存器TIMx_CCR的值A乘以觸發脈沖的時鐘周期,即輸出PWM的占空比為A/(N+1) 。
4        PWM配置步驟4.1         配置GPIO
void LED_Config(void)
{
         GPIO_InitTypeDefGPIO_InitStructure;

         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO,ENABLE);//開啟復用時鐘

         GPIO_InitStructure.GPIO_Pin=  LED_RED| LED_BLUE | LED_GREEN;
    GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
         GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP;
         GPIO_Init(GPIOC,&GPIO_InitStructure);

         GPIO_SetBits(GPIOC,LED_RED | LED_BLUE | LED_GREEN);
}
4.2         配置定時器
void TIMER_Config(void)
{
         TIM_TimeBaseInitTypeDef     TIM_BaseInitStructure;
         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);

         GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);

         TIM_BaseInitStructure.TIM_Period= 255;
         TIM_BaseInitStructure.TIM_Prescaler= 0;
         TIM_BaseInitStructure.TIM_ClockDivision= TIM_CKD_DIV1;
         TIM_BaseInitStructure.TIM_CounterMode= TIM_CounterMode_Up;

         TIM_TimeBaseInit(TIM3,&TIM_BaseInitStructure);
         TIM_ARRPreloadConfig(TIM3,ENABLE);
         TIM_Cmd(TIM3,ENABLE);
}
4.3         配置PWM
void PWM_Config(void)
{
         TIM_OCInitTypeDef  TIM_OCInitStructure;

         TIM_OCStructInit(&TIM_OCInitStructure);   
         TIM_OCInitStructure.TIM_Pulse= 0;   
         TIM_OCInitStructure.TIM_OCMode= TIM_OCMode_PWM1;                                                                       //選擇模式1
         TIM_OCInitStructure.TIM_OutputState= TIM_OutputState_Enable;  
         TIM_OCInitStructure.TIM_OCPolarity= TIM_OCPolarity_Low      //極性為高電平有效

    TIM_OC2Init(TIM3, &TIM_OCInitStructure);
         TIM_OC3Init(TIM3,&TIM_OCInitStructure);
         TIM_OC4Init(TIM3,&TIM_OCInitStructure);         

         TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);
         TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable);
         TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable);

TIM_CtrlPWMOutputs(TIM3,ENABLE);   
}
4.4         小結
PWM模式1:
在向上計數時,一旦TIMx_CNT<TIMx_CCR1時通道1為有效電平,否則為無效電平;在向下計數時,一旦TIMx_CNT>TIMx_CCR1時通道1為無效電平(OC1REF=0),否則為有效電平(OC1REF=1)。
PWM模式2:
在向上計數時,一旦TIMx_CNT<TIMx_CCR1時通道1為無效電平,否則為有效電平;在向下計數時,一旦TIMx_CNT>TIMx_CCR1時通道1為有效電平,否則為無效電平。
同時輸出的有效點評還與極性配置有關:
TIM_OCInitStructure.TIM_OCPolarity =TIM_OCPolarity_High;
此配置是高電平為有效電平,反之亦然。
5        UART配置步驟5.1         配置UART1以及對應的GPIO
void Usart_Config(uint32_t BaudRate)
{
     GPIO_InitTypeDef GPIO_InitStructure;
     USART_InitTypeDef USART_InitStructure;

     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);   
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
     GPIO_Init(GPIOA, &GPIO_InitStructure);

     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
     GPIO_Init(GPIOA, &GPIO_InitStructure);

     /*USART 初始化設置*/
     USART_InitStructure.USART_BaudRate = BaudRate;        
     USART_InitStructure.USART_WordLength = USART_WordLength_8b;  
     USART_InitStructure.USART_StopBits = USART_StopBits_1;         
     USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None;
     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;   

     USART_Init(USART_PC, &USART_InitStructure);

     USART_ITConfig(USART_PC, USART_IT_RXNE, ENABLE);  //開啟串口接收中斷
           USART_ITConfig(USART_PC, USART_IT_IDLE,ENABLE);  //開啟串口接收中斷

     USART_Cmd(USART_PC, ENABLE);
}
5.2         配置中斷
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;

  /*Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

  /*Enable the USARTy Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}
5.3         中斷函數
void USART1_IRQHandler(void)
{
uint8_t clear = clear;

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
  {
                   USART_ClearITPendingBit(USART1,USART_IT_RXNE);
   /* Read one byte from the receive data register */
   RxBuffer[RxCounter++] = USART_ReceiveData(USART1);
  }
         elseif(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
         {
                   clear= USART1->SR;
                   clear= USART1->DR;                     //先讀SR再讀DR,為了清除IDLE中斷
                   RxNumber= RxCounter;
                   RxCounter= 0;                                               //計數清零
                   IDLE_Flag= 1;                                       //標記接收到一幀的數據
         }
}
5.4         小結
STM32單片機可以實現接收不定長度字節數據。由于STM32單片機帶IDLE中斷,利用這個中斷,可以接收不定長字節的數據。由于STM32屬于ARM單片機,所以這篇文章的方法也適合其他的ARM單片機。
IDLE就是串口收到一幀數據后,發生的中斷。比如說給單片機一次發來1個字節,或者一次發來8個字節,這些一次發來的數據,就稱為一幀數據,也可以叫做一包數據。 一幀數據結束后,就會產生IDLE中斷。這個中斷十分有用,可以省去了好多判斷的麻煩。
6        ASCII碼轉換為數字6.1         實現步驟:
                            /*讀取第1部分數值 */
                            while(RxBuffer[ i]!=  ','){         i++;  len++;}//如果不為','長度加1

                            for(j=i-len;j<i; j++){
                                     value= RxBuffer[j]&0x0f;         //ascii碼轉換為數字
                                     pwm_red+= value * Power(len-1);
                                     len--;
                            }

                            i++;
                            len= 0;

                            /*讀取第2部分數值 */
                            while(RxBuffer[ i]!=  ','){         i++;  len++;}
                            for(j=i-len;j<i; j++){
                                     value= RxBuffer[j]&0x0f;         //ascii碼轉換為數字
                                     pwm_green+= value * Power(len-1);
                                     len--;
                            }                           
                            i++;  
                            len= 0;
                            /*讀取第3部分數值 */
                            while(RxBuffer[ i] !=  '\0'){      i++;  len++;}
                            for(j=i-len;j<i; j++){
                                     value= RxBuffer[j]&0x0f;         //ascii碼轉換為數字
                                     pwm_blue+= value * Power(len-1);
                                     len--;
                            }
                            RedOutput(pwm_red);
                            GreenOutput(pwm_green);
                            BlueOutput(pwm_blue);
                            pwm_red= 0;
                            pwm_green= 0;
                            pwm_blue= 0;
                            for(i=0;i<11; i++)               RxBuffer[ i] =NULL;//清除數組
                            i= 0;
                            len= 0;
                   }
         }
}
6.2         10n次方函數
uint8_t Power(uint8_t pow)
{
         uint8_ti;
         uint8_tsum = 1;

         for(i=0;i<pow; i++)   sum *= 10;

         returnsum;
}
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:231256 發表于 2017-9-5 21:29 | 只看該作者
方法不錯,也可以用紅外遙控之類的來進行數字輸出,調出想要的PWM波型,驅動不同亮度的LED燈。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲欧美国产精品一区二区 | 一区精品国产欧美在线 | 国产黄色在线观看 | 又黑又粗又长的欧美一区 | 美日韩中文字幕 | 亚洲精品二区 | 国产成人小视频 | 中文字幕在线一区二区三区 | 亚洲精品一区二区三区丝袜 | 国产免费视频 | 中文字幕一区二区三区在线观看 | 亚洲精品国产电影 | 视频一区二区三区在线观看 | 亚洲狠狠丁香婷婷综合久久久 | 国产精品视频一区二区三区不卡 | 狠狠久久综合 | 欧美日韩一 | 五月天天丁香婷婷在线中 | 国产精品99久久免费观看 | 丝袜 亚洲 欧美 日韩 综合 | 天天av网| 色av一区二区 | 日本精品国产 | 天堂三级| 国产欧美日韩精品一区 | 色网站入口 | 天天色图 | 国产剧情一区 | 一区二区三区中文字幕 | 日韩国产黄色片 | 免费一区二区 | 99国产精品一区二区三区 | 亚洲日韩欧美一区二区在线 | 欧美一级一区 | 国产精品久久久久久亚洲调教 | 欧美激情精品久久久久久免费 | 一区二区三区中文字幕 | 成人高清视频在线观看 | 色婷婷九月| 欧美一区免费 | 亚洲日本欧美日韩高观看 |