最近公司事情太多了,將近一個(gè)月沒有更新了。 我的想法是把我用到的所有單片機(jī)都更新一下(當(dāng)然不局限于這些,后期也會(huì)更新一些其他和嵌入式相關(guān)的知識(shí)點(diǎn),我就想著先把STM32這整個(gè)更新完,再去更新其他的,包括STM32下 RTOS、UI(emwin,LVGL)還有一些項(xiàng)目上的經(jīng)驗(yàn)什么的。 等STM32相關(guān)的更新完之后會(huì)寫其他的東西。 也會(huì)根據(jù)實(shí)際的情況進(jìn)行其他內(nèi)容的更新:我用過STM32 CH32、HC32F4、S32K148等,還有各種傳感器啥的。
從本章節(jié)開始我們進(jìn)行一個(gè)STM32實(shí)戰(zhàn)操作,為此我還特意畫了個(gè)簡單的板子。 是物聯(lián)網(wǎng)相關(guān)的,后面會(huì)設(shè)計(jì)一個(gè)BMS的板子來寫一下。
1-編寫第一個(gè)程序點(diǎn)亮LED燈
下面是原理圖,連接的是PC0-PC7引腳:
1static void Led_Cofig(void)
2{
3 /*定義一個(gè)GPIO_InitTypeDef類型的結(jié)構(gòu)體*/
4 GPIO_InitTypeDef GPIO_InitStructure;
5 /*開啟LED相關(guān)的GPIO外設(shè)時(shí)鐘*/
6 RCC_APB2PeriphClockCmd(LED_GPIO_CLCK, ENABLE);
7 /*選擇要控制的GPIO引腳*/
8 GPIO_InitStructure.GPIO_Pin = LED1_GPIO_PIN;
9 /*設(shè)置引腳模式為通用推挽輸出*/
10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
11 /*設(shè)置引腳速率為50MHz */
12 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //(指的是內(nèi)部驅(qū)動(dòng)電路的響應(yīng)速度,速度越大越快,一般情況是有多個(gè)不同的速度,也可根據(jù)自己的需要安排)
13 GPIO_Init(LED_GPIO_PORT, &GPIO_InitStructure);
14 /* 關(guān)閉led燈 */
15 GPIO_SetBits(LED_GPIO_PORT, LED1_GPIO_PIN);
16}
1/*LED連接GPIO的定義,程序開發(fā)者如果要修改引腳只需要修改這里就好*/
2#define LED_GPIO_PORT GPIOC // GPIO端口定義,為了方便修改
3#define LED_GPIO_CLCK RCC_APB2Periph_GPIOC /* GPIO端口時(shí)鐘 */
4/*GPIO引腳*/
5#define LED1_GPIO_PIN GPIO_Pin_0
6#define LED2_GPIO_PIN GPIO_Pin_1
7#define LED3_GPIO_PIN GPIO_Pin_2
8#define LED4_GPIO_PIN GPIO_Pin_3
9#define LED5_GPIO_PIN GPIO_Pin_4
10#define LED6_GPIO_PIN GPIO_Pin_5
11#define LED7_GPIO_PIN GPIO_Pin_6
12#define LED8_GPIO_PIN GPIO_Pin_7
2-代碼說明
1:GPIO_InitTypeDef GPIO_InitStructure 語句是聲明一個(gè)結(jié)構(gòu)體GPIO_InitStructure結(jié)構(gòu)體原型由GPIO_InitTypeDef確定(這點(diǎn)是C語言的基礎(chǔ)知識(shí))設(shè)置完之后就可以對(duì)GPIO_Init(LED_GPIO_PORT, &GPIO_InitStructure); 進(jìn)行操作。
2:GPIO_SetBits()是庫函數(shù),可以對(duì)多個(gè)I/O口同時(shí)置1。
這里還有一個(gè)GPIO_ResetBits()庫函數(shù),可以對(duì)多個(gè)I/O口置0。
注釋和工程添加就不說了,網(wǎng)上相關(guān)的也挺多的。
GPIO_InitStructure.XXXX后面的speed什么的也不說了,不知道的可以去STM32知識(shí)篇看看。 這里主要講述函數(shù)配置什么的,畢竟是實(shí)戰(zhàn)嘛,指定是不能都介紹的。
3-main函數(shù)
1int main()
2{
3 LED_Init();
4 while (1)
5 {
6
7 GPIO_ResetBits(LED_GPIO_PORT, LED1_GPIO_PIN);
8 }
9}
因?yàn)榻拥氖钦龢O,點(diǎn)亮LED燈兩端需要電壓差,所以在這里使用GPIO_ResetBits才能點(diǎn)亮,如果你的一端接的是地,則是使用GPIO_SetBits。 這點(diǎn)要知道。 就是不管是哪種器件,只有保持電壓差才能進(jìn)行一個(gè)數(shù)據(jù)的接收,燈的點(diǎn)亮,我認(rèn)為是這樣的,可以說是所有的元器件芯片都是這樣的,但不是絕對(duì)的,只能說大部分。
上面點(diǎn)亮之后,我們這樣感覺修改太麻煩。 可以在頭文件之后對(duì)其設(shè)置一個(gè)宏定義函數(shù),如下:
1/*標(biāo)準(zhǔn)庫點(diǎn)亮LED燈*/
2/*當(dāng)a=0時(shí),LED燈滅,當(dāng)LED=1時(shí),LED燈亮*/
3#define LED1(a) \\
4 if (a) \\
5 { \\
6 GPIO_ResetBits(LED_GPIO_PORT, LED1_GPIO_PIN); \\
7 } \\
8 else \\
9 GPIO_SetBits(LED_GPIO_PORT, LED1_GPIO_PIN);
當(dāng)a=1時(shí),燈亮,0時(shí)燈滅。
1int main()
2{
3 LED_Init();
4 while (1)
5 {
6 //GPIO_ResetBits(LED_GPIO_PORT,LED1_GPIO_PIN);
7 LED1(1);
8 }
9}
下面說一說位操作,這是嵌入式開發(fā)中最常用的。
5-位操作
什么是位操作,我認(rèn)為位操作就是吃羊肉串,從前面吃,從后面吃,從中間吃這樣的。 但是官方說法比我這好聽。 其實(shí)位操作操作的是二進(jìn)制或者十六進(jìn)制這樣的,你看像不像你在吃羊肉串,比如二進(jìn)制0b0000 0001,你看從后面讀取就相當(dāng)于你從后面開始吃羊肉串。 下面說正經(jīng)的。
我們對(duì)上面這個(gè)表進(jìn)行一些介紹和使用說明
- 在不改變其他位的狀況下,對(duì)某幾個(gè)位賦值
針對(duì)這種情況,應(yīng)該怎么做才能實(shí)現(xiàn)對(duì)某幾個(gè)位賦值呢? 我們可以把“&”和“|” 兩個(gè)位操作結(jié)合起來使用,步驟如下。
(1)先對(duì)需要設(shè)置的位用“&”操作符進(jìn)行清零操作。
(2)再用“|” 操作符賦值。
例如,在初始化時(shí),若配置PD8引腳為推挽輸出、速度為50 MHz,需將GPIOD->CRH的0~3位設(shè)置為3(即二進(jìn)制0011B),這時(shí)可先對(duì)寄存器的0~3位進(jìn)行“&”清零操作。
1GPIOD->CRH&=0Xfffffff0; //清掉原來的設(shè)置,同時(shí)不影響其他位設(shè)置
然后再與需要設(shè)置的值進(jìn)行“|” 運(yùn)算:
1GPIOD->CRH|=0X00000003; //設(shè)置0~3 位的值為3,不改變其他位的值
- 使用移位操作,提高代碼的可讀性
移位操作在STM32程序開發(fā)中也非常重要。 比如在初始化時(shí),若需要使能GPIOD口的時(shí)鐘,就可使用移位操作來實(shí)現(xiàn),使能PORTD時(shí)鐘的語句是:
1RCC->APB2ENR|=1<<5;
使能GPIOD和GPIOE口時(shí)鐘的語句是:
1RCC->APB2ENR|=3<<5;
這個(gè)左移位操作,就是將RCC->APB2ENR寄存器的第5位設(shè)置為1,使能PORTD時(shí)鐘。 為什么要通過左移而不是直接設(shè)置一個(gè)固定的值來對(duì)寄存器進(jìn)行操作呢? 其實(shí),這樣做是為了提高代碼的可讀性以及可重用性。 讀者可以很直觀明了地看到,這行代碼是將第5位設(shè)置為1。 如果寫成:
1RCC->APB2ENR =0x00000020;
但是這樣代碼寫出來不太友好,首先是不可重復(fù)使用,其次真煩呀。 反正這種挺多的,大家可以自己多練練。
- 取反位操作的應(yīng)用
SR寄存器的每一位都代表一個(gè)狀態(tài)。 在某個(gè)時(shí)刻,我們希望設(shè)置某一位為0,同時(shí)其他位都保留為1,簡單的做法是直接給寄存器設(shè)置一個(gè)值。
1TIMx->SR=0xF7FF;
上述代碼設(shè)置第11位為0,但代碼可讀性不太友好。 但是我們可以這樣寫:
1#define TIM_FLAG_Update ((uint16_t)0x0001)
2TIMx->SR &=~(TIM_FLAG_Update <<11);
從上面的代碼中,我們可以從第一條語句看出,宏定義了TIM_FLAG_Update第0位是1,其他位是0; 第二條語句讓TIM_FLAG_Update左移11位取反,第11位就為0,其他位都為1; 最后通過按位與操作,使第11位為0,其他位保持不變。 這樣,讀者就能很容易地看明白代碼,所以代碼的可讀性也就非常強(qiáng)的。
-
單片機(jī)
+關(guān)注
關(guān)注
6063文章
44929瀏覽量
647220 -
嵌入式
+關(guān)注
關(guān)注
5141文章
19544瀏覽量
315212 -
led燈
+關(guān)注
關(guān)注
22文章
1595瀏覽量
109371 -
STM32
+關(guān)注
關(guān)注
2290文章
11017瀏覽量
362487 -
RTOS
+關(guān)注
關(guān)注
24文章
842瀏覽量
120791
發(fā)布評(píng)論請(qǐng)先 登錄
單片機(jī)入門之點(diǎn)亮LED燈

請(qǐng)問51單片機(jī)/STM32單片機(jī)/嵌入式Linux是如何點(diǎn)亮LED燈的?
使用51單片機(jī)Keil工程建立點(diǎn)亮LED燈的詳細(xì)教程說明

如何使用單片機(jī)點(diǎn)亮LED燈

單片機(jī)控制LED燈點(diǎn)亮的實(shí)驗(yàn)資料說明

使用單片機(jī)點(diǎn)亮LED燈的程序和工程文件免費(fèi)下載

51單片機(jī)——LED燈的點(diǎn)亮

【藍(lán)橋杯】單片機(jī)學(xué)習(xí)(2)——點(diǎn)亮LED小燈

單片機(jī)零基礎(chǔ)入門(1):點(diǎn)亮1個(gè)LED燈

51單片機(jī)---點(diǎn)亮LED燈

51單片機(jī)——點(diǎn)亮一個(gè)LED燈

基于51單片機(jī)點(diǎn)亮LED燈

評(píng)論