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

標(biāo)題: STM32串口控制LED燈閃爍或者呼吸效果 [打印本頁(yè)]

作者: 新手在線求帶    時(shí)間: 2020-8-24 12:05
標(biāo)題: STM32串口控制LED燈閃爍或者呼吸效果
目錄


1、準(zhǔn)備工作

1.首先我們需要準(zhǔn)備32的最小系統(tǒng)板或者開(kāi)發(fā)板。
2.準(zhǔn)備一個(gè)LED燈(如果使用板子上的燈來(lái)實(shí)現(xiàn)則不需要,下面我是使用最小系統(tǒng)板上的LED燈來(lái)實(shí)現(xiàn))。
3.若干杜邦線。
4.軟件方面的準(zhǔn)備,我是直接使用開(kāi)源PWM源碼進(jìn)行修改。


2、思路分析

一、使用串口調(diào)試助手向單片機(jī)發(fā)送數(shù)據(jù)(這個(gè)數(shù)據(jù)可以是一個(gè)字符,也可以是字符串,根據(jù)個(gè)人需求),我們發(fā)送的數(shù)據(jù)被單片機(jī)接收到后,會(huì)被保存在數(shù)據(jù)緩沖區(qū)USART_RX_BUF這個(gè)函數(shù)中。
二、我們的數(shù)據(jù)是存在USART_RX_BUF函數(shù)中,只要我們對(duì)USART_RX_BUF函數(shù)中的數(shù)據(jù)進(jìn)行判斷就可以讓它實(shí)現(xiàn)不同的功能,這個(gè)判斷可以按位操作,也可以使用數(shù)組的方式進(jìn)行判斷。
三、主函數(shù)中寫(xiě)入我們需要實(shí)現(xiàn)的功能函數(shù),主要使用IF判斷語(yǔ)句,來(lái)進(jìn)行判斷。
下面來(lái)看看實(shí)際操作。


3、實(shí)際操作

1)如果你也是使用開(kāi)源的PWM模板的話,第一步就可以省略了,第一步主要做一些使能串口和定義串口,定時(shí)器等的工作,我這里我使用的是定時(shí)器3的通道2——PB5(部分重映射,因?yàn)樽钚∠到y(tǒng)板的LED燈是對(duì)應(yīng)PC13口的,到時(shí)候看效果還要使用一根杜邦線把PB5和PC13連在一起。如果自己準(zhǔn)備了LED的小伙伴也可以直接接自己的LED但是最好要接一個(gè)保護(hù)電阻,還有要與單片機(jī)共地哦)這些都是開(kāi)源模板里面已經(jīng)幫我們定義好的,我們直接使用就行。如果是想自己寫(xiě)的小伙伴開(kāi)源參考下面的代碼

GPIO_InitTypeDef GPIO_InitStructure;

        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

        TIM_OCInitTypeDef  TIM_OCInitStructure;

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);        //使能定時(shí)器3時(shí)鐘

         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外設(shè)和AFIO復(fù)用功能模塊時(shí)鐘

        GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射  TIM3_CH2->PB5   

   //設(shè)置該引腳為復(fù)用輸出功能,輸出TIM3 CH2的PWM脈沖波形        GPIOB.5

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2

        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //復(fù)用推挽輸出

        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

        GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO

   //初始化TIM3

        TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個(gè)更新事件裝入活動(dòng)的自動(dòng)重裝載寄存器周期的值

        TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置用來(lái)作為T(mén)IMx時(shí)鐘頻率除數(shù)的預(yù)分頻值

        TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim

        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上計(jì)數(shù)模式

        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位

        //初始化TIM3 Channel2 PWM模式         

        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //選擇定時(shí)器模式:TIM脈沖寬度調(diào)制模式2

         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能

        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高

        TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根據(jù)T指定的參數(shù)初始化外設(shè)TIM3 OC2

        TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的預(yù)裝載寄存器

        TIM_Cmd(TIM3, ENABLE);  //使能TIM3

上面這串代碼就是使能了定時(shí)器3的通道2 ,和配置了相關(guān)的GPIO口。這就完成了第一步。
2)使能串口和配置串口,USART1_TX --GPIOA.9(發(fā)送);USART1_RX—GPIOA.10(接收),串口1的發(fā)生和接收分別對(duì)應(yīng)著PA9和PA10,所以我們要使能和配置這兩個(gè)口,把PA9配置成輸出口,PA10配置成輸入口。然后還要使能中斷,其實(shí)在這個(gè)項(xiàng)目中,中斷不是必要的 ,但是最好也要搞一下。還要寫(xiě)中斷服務(wù)函數(shù),根據(jù)自己需要寫(xiě),我這里我只是把它用作了判斷數(shù)據(jù)是否接收成功。如果對(duì)應(yīng)串口這個(gè)不是很了解的,也可以看我上一篇文章,是介紹串口和串口中斷的。分析到這些就OK了,下面上代碼。


  1. <font face="-apple-system, SF UI Text, Arial, PingFang SC, Hiragino Sans GB, Microsoft YaHei, WenQuanYi Micro Hei, sans-serif"><font color="#4d4d4d"> GPIO_InitTypeDef GPIO_InitStructure;
  2.         USART_InitTypeDef USART_InitStructure;
  3.         NVIC_InitTypeDef NVIC_InitStructure;
  4.          
  5.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);        //使能USART1,GPIOA時(shí)鐘
  6.   
  7.         //USART1_TX   GPIOA.9
  8.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  9.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  10.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //復(fù)用推挽輸出
  11.   GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
  12.    
  13.   //USART1_RX          GPIOA.10初始化
  14.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  15.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入
  16.   GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

  17.   
  18.         //Usart1 NVIC 配置
  19.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  20.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//搶占優(yōu)先級(jí)3
  21.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;                //子優(yōu)先級(jí)3
  22.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能
  23.         NVIC_Init(&NVIC_InitStructure);        //根據(jù)指定的參數(shù)初始化VIC寄存器
  24.   
  25.    //USART 初始化設(shè)置

  26.         USART_InitStructure.USART_BaudRate = bound;//串口波特率
  27.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長(zhǎng)為8位數(shù)據(jù)格式
  28.         USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個(gè)停止位
  29.         USART_InitStructure.USART_Parity = USART_Parity_No;//無(wú)奇偶校驗(yàn)位
  30.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無(wú)硬件數(shù)據(jù)流控制
  31.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;        //收發(fā)模式

  32.   USART_Init(USART1, &USART_InitStructure); //初始化串口1
  33.   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//開(kāi)啟串口接受中斷
  34.   USART_Cmd(USART1, ENABLE);                    //使能串口1 </font></font>
復(fù)制代碼
上面這些是串口的基本配置,下面是中斷服務(wù)函數(shù)

  1. void USART1_IRQHandler(void)                        //串口1中斷服務(wù)程序
  2.         {
  3.         u8 Res;
  4. #if SYSTEM_SUPPORT_OS                 //如果SYSTEM_SUPPORT_OS為真,則需要支持OS.
  5.         OSIntEnter();   
  6. #endif
  7.         if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中斷(接收到的數(shù)據(jù)必須是0x0d 0x0a結(jié)尾)
  8.                 {
  9.                 Res =USART_ReceiveData(USART1);        //讀取接收到的數(shù)據(jù)
  10.                
  11.                 if((USART_RX_STA&0x8000)==0)//接收未完成
  12.                         {
  13.                         if(USART_RX_STA&0x4000)//接收到了0x0d
  14.                                 {
  15.                                 if(Res!=0x0a)USART_RX_STA=0;//接收錯(cuò)誤,重新開(kāi)始
  16.                                 else USART_RX_STA|=0x8000;        //接收完成了
  17.                                 }
  18.                         else //還沒(méi)收到0X0D
  19.                                 {        
  20.                                 if(Res==0x0d)USART_RX_STA|=0x4000;
  21.                                 else
  22.                                         {
  23.                                         USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
  24.                                         USART_RX_STA++;
  25.                                         if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收數(shù)據(jù)錯(cuò)誤,重新開(kāi)始接收         
  26.                                         }                 
  27.                                 }
  28.                         }                    
  29.      }
  30. #if SYSTEM_SUPPORT_OS         //如果SYSTEM_SUPPORT_OS為真,則需要支持OS.
  31.         OSIntExit();                                                                                          
  32. #endif
  33. }
復(fù)制代碼
如果想要主函數(shù)中比較簡(jiǎn)潔的話,也可以把判斷的代碼放到中斷服務(wù)函數(shù)里面來(lái),每次我們從串口發(fā)送一個(gè)數(shù)據(jù)過(guò)來(lái),如果你寫(xiě)了中斷的話,它都會(huì)進(jìn)行中斷服務(wù)函數(shù)中的。
3)這個(gè)也是最重要的一步,前兩步在源碼中都有的,只要你根據(jù)你需要改就行。這步我們說(shuō)如何控制LED的閃爍或者是呼吸的效果。我使用的是一個(gè)位一個(gè)位的判斷,這樣子比較的燒芯片,但是我當(dāng)時(shí)想到的是這個(gè)辦法,后面我又知道可以使用數(shù)組進(jìn)行判斷,這個(gè)數(shù)組函數(shù)是C語(yǔ)言中的,感興趣的小伙伴可以去查查,我這里主要講燒芯片的辦法,首先我先判斷串口調(diào)試助手發(fā)送進(jìn)來(lái)的是不是“huxi”這個(gè)數(shù)據(jù),如果是我就會(huì)令一個(gè)變量,這里是t,t=1,這樣后面我們就可以直接判斷t是否等于1來(lái)判斷要不要實(shí)現(xiàn)呼吸這個(gè)效果了,后面需要清除接收標(biāo)記 USART_RX_STA=0;這樣之后串口才能重新接收數(shù)據(jù)。

  1. if(USART_RX_BUF[0]=='h'&&USART_RX_BUF[1]=='u'&&USART_RX_BUF[2]=='x'
  2.                                 &&USART_RX_BUF[3]=='i')
  3.                         {
  4.                         
  5.                                 t=1;
  6.                                 USART_RX_STA=0;
  7. //                                printf("t2.txt=\"呼吸\"\xff\xff\xff");

  8.                         }
復(fù)制代碼
  1. if(t==1)
  2.                 {
  3.                         delay_ms(10);//去抖動(dòng)
  4.                 if(dir)led0pwmval++;
  5.                 else led0pwmval--;

  6.                  if(led0pwmval>200)dir=0;
  7.                 if(led0pwmval==0)dir=1;                                                                                 
  8.                 TIM_SetCompare2(TIM3,led0pwmval);

  9.                                 
  10.                 }
復(fù)制代碼
上面這兩個(gè)代碼就是實(shí)現(xiàn)呼吸燈效果的,閃爍效果的做法跟呼吸燈是一樣的,也是先進(jìn)行判斷,然后調(diào)用判斷結(jié)果,我這里是判斷接收是否等于“shanshuo”這個(gè)數(shù)據(jù),如果等于t=0,后面調(diào)用t這個(gè)變量就可以了,話不多說(shuō),上代碼。
  1. else if(USART_RX_BUF[0]=='s'&&USART_RX_BUF[1]=='h'&&USART_RX_BUF[2]=='a'
  2.                                 &&USART_RX_BUF[3]=='n'&&USART_RX_BUF[4]=='s'&&USART_RX_BUF[5]=='h'&&USART_RX_BUF[6]=='u'&&USART_RX_BUF[7]=='o')
  3.                         {
  4.                           
  5.                                 t=0;
  6.                                 USART_RX_STA=0;        
  7.                         
  8.                         }
復(fù)制代碼
  1. if(t==0)
  2.         {
  3.                 TIM_SetCompare2(TIM3,0);
  4.     delay_ms(300);
  5.    TIM_SetCompare2(TIM3,899);
  6.           delay_ms(300);


  7.         }
復(fù)制代碼
這樣使用兩次判斷就可以把這兩個(gè)功能都實(shí)現(xiàn)了。不過(guò)有一個(gè)小問(wèn)題是,我們這樣子接收判斷是把原來(lái)存在數(shù)據(jù)緩沖區(qū)USART_RX_BUF中的數(shù)據(jù)給覆蓋掉的,如果前一個(gè)數(shù)據(jù)的長(zhǎng)度比后一個(gè)要長(zhǎng),那就會(huì)覆蓋不完,最好還有加一個(gè)清除函數(shù),這里介紹一種辦法使用運(yùn)行庫(kù)函數(shù)memset():memset(str, 0, sizeof(str));這樣就可以把緩沖區(qū)的數(shù)據(jù)清除掉,當(dāng)然還有其他辦法,但是我就想到這個(gè),可能不好用。但是我們這個(gè)項(xiàng)目里面覆蓋完不完并不會(huì)影響結(jié)果,所以也可以用,不過(guò)在需要把數(shù)據(jù)打印到串口這樣的項(xiàng)目中,就很有必要把之前數(shù)據(jù)給清除掉,不然容易出錯(cuò)。
為了代碼的完整,下面我把整個(gè)主函數(shù)的代碼給貼出來(lái),給各位伙伴參考。
  1. int main(void)
  2. {               
  3.    
  4.          u16 t;  
  5.          u16 led0pwmval=0;
  6.         u8 dir=1;        
  7.         delay_init();                     //延時(shí)函數(shù)初始化         
  8.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);          //設(shè)置NVIC中斷分組2:2位搶占優(yōu)先級(jí),2位響應(yīng)優(yōu)先級(jí)
  9.         uart_init(115200);         //串口初始化為115200
  10.          LED_Init();                             //LED端口初始化
  11.          TIM3_PWM_Init(899,0);         //不分頻。PWM頻率=72000000/900=80Khz
  12.   
  13.          while(1)
  14.         {

  15.                         if(USART_RX_BUF[0]=='h'&&USART_RX_BUF[1]=='u'&&USART_RX_BUF[2]=='x'
  16.                                 &&USART_RX_BUF[3]=='i')
  17.                         {
  18.                         
  19.                                 t=1;
  20.                                 USART_RX_STA=0;


  21.                         }
  22.                         else if(USART_RX_BUF[0]=='s'&&USART_RX_BUF[1]=='h'&&USART_RX_BUF[2]=='a'
  23.                                 &&USART_RX_BUF[3]=='n'&&USART_RX_BUF[4]=='s'&&USART_RX_BUF[5]=='h'&&USART_RX_BUF[6]=='u'&&USART_RX_BUF[7]=='o')
  24.                         {
  25.                           
  26.                                 t=0;
  27.                                 USART_RX_STA=0;        
  28.                         
  29.                         }
  30.                

  31.                 if(t==1)
  32.                 {
  33.                         delay_ms(10);//去抖動(dòng)
  34.                 if(dir)led0pwmval++;
  35.                 else led0pwmval--;

  36.                  if(led0pwmval>200)dir=0;
  37.                 if(led0pwmval==0)dir=1;                                                                                 
  38.                 TIM_SetCompare2(TIM3,led0pwmval);

  39.                                 
  40.                 }
  41.         if(t==0)
  42.         {
  43.                 TIM_SetCompare2(TIM3,0);
  44.     delay_ms(300);
  45.    TIM_SetCompare2(TIM3,899);
  46.           delay_ms(300);


  47.         }
  48.                                 
  49.         
  50. }
  51. }
復(fù)制代碼

4、小結(jié)

1.在這個(gè)項(xiàng)目中要注意把PB5和PC13用杜邦線連到一樣哦,不然就看不到效果啦。
2.還有一個(gè)易錯(cuò)點(diǎn)就是,在閃爍這個(gè)功能代碼中,很多人首先想到的肯定是讓那個(gè)GPIO口的電平置高或者置低來(lái)控制燈的閃爍,但是這樣子的話,你就不可以只用一個(gè)燈來(lái)實(shí)現(xiàn)呼吸和閃爍之間的轉(zhuǎn)換了,你需要使用兩個(gè)燈,一個(gè)呼吸一個(gè)閃爍,這樣子是比較麻煩的。但是也根據(jù)個(gè)人需要吧,如果想要只用一個(gè)燈實(shí)現(xiàn)兩個(gè)效果,就使用上面的方法,呼吸和閃爍都使用定時(shí)器3通道2來(lái)控制。這樣就可以達(dá)到轉(zhuǎn)換自如了。
3.就是數(shù)據(jù)覆蓋的問(wèn)題,這個(gè)也是根據(jù)你要做的項(xiàng)目要解決吧,可以清除,也可以不用。
4.上面的辦法只是控制呼吸和閃爍的一種辦法,或許復(fù)雜了,希望有更加簡(jiǎn)單辦法的大佬指導(dǎo)一下,我也是剛剛學(xué)習(xí),如有不懂的,可以私信交流,分享到此,謝謝.



作者: seanking    時(shí)間: 2020-8-25 08:02
115200的波特率每ms至少能夠傳輸1字節(jié)數(shù)據(jù)
如果在main函數(shù)中處理命令,僅軟延時(shí)就有600ms,不建議這么寫(xiě)
作者: 新手在線求帶    時(shí)間: 2020-9-2 12:54
seanking 發(fā)表于 2020-8-25 08:02
115200的波特率每ms至少能夠傳輸1字節(jié)數(shù)據(jù)
如果在main函數(shù)中處理命令,僅軟延時(shí)就有600ms,不建議這么寫(xiě)

好的,感謝指點(diǎn)
作者: 1244986336    時(shí)間: 2020-9-3 14:19
樓主呼吸燈控制寫(xiě)的挺詳細(xì)的,學(xué)習(xí)一下
作者: gentleyidao    時(shí)間: 2020-9-3 17:33
想做個(gè)呼吸燈的玩具,正好用上
作者: liding12356    時(shí)間: 2020-9-3 18:48
樓主這個(gè)成本有點(diǎn)大呀,可以通過(guò)多點(diǎn)的LED來(lái)做更好的
作者: fmqwh626    時(shí)間: 2020-9-17 17:11
試驗(yàn)下先。。。。。。
作者: jmpw    時(shí)間: 2020-9-18 10:13
一個(gè)燈閃也要弄得這么復(fù)雜嗎
作者: Beautiful_me    時(shí)間: 2020-9-23 18:30
串口接收數(shù)據(jù)那里寫(xiě)的不錯(cuò),解決了我的迷惑
作者: lovekmjb    時(shí)間: 2020-9-24 14:45
jmpw 發(fā)表于 2020-9-18 10:13
一個(gè)燈閃也要弄得這么復(fù)雜嗎

是漸變
作者: ggyu7    時(shí)間: 2020-12-23 13:14
講的真好
作者: 真是又菜又愛(ài)玩    時(shí)間: 2020-12-28 14:07
感謝樓主的分享。收藏備用、學(xué)習(xí)
作者: ii11nnocent    時(shí)間: 2020-12-28 15:57
學(xué)習(xí)了,講解很詳細(xì),最近正在學(xué)習(xí)STM32,這個(gè)教程串口、定時(shí)器和PWM都用到了。
作者: spookerst    時(shí)間: 2020-12-28 16:12
樓主控制寫(xiě)的挺詳細(xì)的,學(xué)習(xí)一下
作者: 格林楓景    時(shí)間: 2021-1-8 16:31
這個(gè)很適合學(xué)習(xí),正好需要


作者: 1244986336    時(shí)間: 2021-1-8 17:38
試一下,寫(xiě)的挺詳細(xì)的
作者: 13978150572    時(shí)間: 2021-2-2 13:34
USART_RX_BUF[0]   USART_RX_STA 是在哪個(gè)地方定義的
作者: jack-tommy    時(shí)間: 2021-2-2 17:44
可以通過(guò)多點(diǎn)的LED來(lái)做更好的
作者: n_n    時(shí)間: 2021-2-9 09:55
呼吸燈控制寫(xiě)的挺詳細(xì)的,學(xué)習(xí)一下




歡迎光臨 (http://m.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 999国产视频| 免费黄色小视频 | 六月丁香综合 | 黄色大毛片 | 色虎网站| 超碰97在线播放 | 午夜tv| 操小妹影院 | 午夜影院在线 | 免费一区二区 | 色天堂视频 | 蜜臀久久99精品久久久久宅男 | 欧美成人极品 | 色婷婷久久综合 | 精产国产伦理一二三区 | 国产精品视频免费在线观看 | 亚洲永久免费 | 国产一区二区三区在线观看视频 | 一区二区三区四区在线 | 福利视频免费 | 亚洲精品区 | 日韩视频在线观看免费 | 不卡的av在线 | 99视频免费在线观看 | 国产毛片在线 | 69精品人人人人 | 久久精品国产一区 | 精品视频国产 | 超碰免费在线 | 国产对白videos麻豆高潮 | 亚洲黄色三级 | 国产永久在线 | 成人免费激情视频 | 成人午夜网站 | 最新日韩av | 中文字幕免费观看视频 | 成人毛片在线播放 | 亚洲精品字幕 | 999久久久久久久久6666 | 中文字幕在线日韩 | 国产欧美一区二区精品性色超碰 |