做項(xiàng)目的編程網(wǎng)站seo關(guān)鍵詞推廣公司
前言:
通過(guò)后面的學(xué)習(xí)掌握了一些邏輯架構(gòu)的知識(shí),通過(guò)復(fù)習(xí)的方式將學(xué)到的裸機(jī)任務(wù)架構(gòu)的知識(shí)運(yùn)用起來(lái),同時(shí)鞏固前面學(xué)到的知識(shí),GPIO的配置等。
?開(kāi)發(fā)板上LED引腳使用示意圖
?注:此次LED燈的點(diǎn)亮凡是是高電平點(diǎn)亮,因?yàn)殡娏魇菑耐獠肯騼?nèi)部進(jìn)行流動(dòng),GND會(huì)引腳的店電平拉低,如果給低電平的話無(wú)法形成電勢(shì)差,電流是無(wú)法流動(dòng)的,給一個(gè)高電平,電流在電壓的作用下點(diǎn)亮LED燈
第一種實(shí)現(xiàn)方式
這種方式類(lèi)似于STM32的庫(kù)函數(shù)編程,不使用結(jié)構(gòu)體使用直接編寫(xiě)的方式進(jìn)行配置,可以作為參考對(duì)比學(xué)習(xí)
1.0 初始化LED
void LED_Init(void)
{// 開(kāi)啟RCC時(shí)鐘rcu_periph_clock_enable(RCU_GPIOA);rcu_periph_clock_enable(RCU_GPIOE);rcu_periph_clock_enable(RCU_GPIOF);// 初始化gpiogpio_init(GPIOA,GPIO_MODE_OUT_PP,GPIO_OSPEED_2MHZ,GPIO_PIN_8);gpio_init(GPIOE,GPIO_MODE_OUT_PP,GPIO_OSPEED_2MHZ,GPIO_PIN_6);gpio_init(GPIOF,GPIO_MODE_OUT_PP,GPIO_OSPEED_2MHZ,GPIO_PIN_6);// 引腳默認(rèn)電平為低電平gpio_bit_reset(GPIOA, GPIO_PIN_8);gpio_bit_reset(GPIOE, GPIO_PIN_6);gpio_bit_reset(GPIOF, GPIO_PIN_6);
}
?2.0 LED點(diǎn)亮熄滅
// 高電平的方式點(diǎn)亮
void LED1_On(void)
{gpio_bit_set(GPIOA, GPIO_PIN_8);
}void LED2_On(void)
{gpio_bit_set(GPIOE, GPIO_PIN_6);
}void LED3_On(void)
{gpio_bit_set(GPIOF, GPIO_PIN_6);
}// 低電平的方式熄滅
void LED1_Off(void)
{gpio_bit_reset(GPIOA, GPIO_PIN_8);
}void LED2_Off(void)
{gpio_bit_reset(GPIOE, GPIO_PIN_6);
}void LED3_Off(void)
{gpio_bit_reset(GPIOF, GPIO_PIN_6);
}
3.0 LED 流水燈函數(shù)
// LED 燈流水效果函數(shù)
void LED_Run(void)
{LED1_On();DelayNms(1000);LED2_On();DelayNms(1000);LED3_On();DelayNms(1000);LED1_Off();LED2_Off();LED3_Off();DelayNms(1000);
}
4.0 LED燈初始化頭文件
#ifndef _LED_DRV_H_
#define _LED_DRV_H_
#include <stdint.h>void LED_Init(void);
void LED1_On(void);
void LED2_On(void);
void LED3_On(void);
void LED1_Off(void);
void LED2_Off(void);
void LED3_Off(void);
void LED_Run(void);#endif
5.0 在主函數(shù)中調(diào)用
使用面向?qū)ο蟮木幋a方式,可以使程序看起來(lái)更為的簡(jiǎn)潔,方便程序的后續(xù)移植。
#include <stdint.h>
#include "gd32f30x.h"
#include "led_drv.h"
#include "delay.h"int main(void)
{DelayInit();LED_Init();while(1){LED_Run();}
}
** 方式 2 **
第二種實(shí)現(xiàn)方式
這種實(shí)現(xiàn)方式是配合結(jié)構(gòu)體與for循環(huán)的方式進(jìn)行實(shí)現(xiàn),可以方便后續(xù)程序的編碼與維護(hù),讓程序可移植性更強(qiáng)。
1.0 創(chuàng)建結(jié)構(gòu)體
// 創(chuàng)建結(jié)構(gòu)體
typedef struct
{// rcu時(shí)鐘rcu_periph_enum rcu;// gpio口uint32_t gpio;// 對(duì)應(yīng)引腳uint32_t pin;}LED_GPIO_t;
?2.0 創(chuàng)建結(jié)構(gòu)體數(shù)組
// 計(jì)算數(shù)組大小
#define LED_NUM_MAX (sizeof(g_gpioList) / sizeof(g_gpioList[0]))//創(chuàng)建結(jié)構(gòu)體數(shù)組
static LED_GPIO_t g_gpioList[] =
{{RCU_GPIOA, GPIOA, GPIO_PIN_8},{RCU_GPIOE, GPIOE, GPIO_PIN_6},{RCU_GPIOF, GPIOF, GPIO_PIN_6}
};
3.0 初始化GPIO
這里使用for循環(huán)遍歷,然后將值一個(gè)個(gè)的賦值給結(jié)構(gòu)體成員變量完成時(shí)鐘的初始化
void LED_DrvInit(void)
{uint8_t i = 0;for(i = 0; i < LED_NUM_MAX; i++){// 開(kāi)啟rcu時(shí)鐘rcu_periph_clock_enable(g_gpioList[i].rcu);// 初始化gpio端口gpio_init(g_gpioList[i].gpio, GPIO_MODE_OUT_PP,GPIO_OSPEED_2MHZ, g_gpioList[i].pin);// 引腳默認(rèn)值gpio_bit_reset(g_gpioList[i].gpio, g_gpioList[i].pin);}}
4.0 點(diǎn)亮LED函數(shù),帶參數(shù)
// LED_ON 點(diǎn)亮
void LED_No(uint8_t ledNo)
{// 判斷l(xiāng)ed編號(hào)的值是否大于最大數(shù)組長(zhǎng)度if(ledNo > LED_NUM_MAX){return; // 返回值無(wú)效}// 點(diǎn)亮gpio_bit_set(g_gpioList[ledNo].gpio, g_gpioList[ledNo].pin);
}
5.0 熄滅LED燈函數(shù),帶參數(shù)
// LED_OFF熄滅
void LED_Off(uint8_t ledNo)
{if (ledNo >= LED_NUM_MAX){return;}gpio_bit_reset(g_gpioList[ledNo].gpio, g_gpioList[ledNo].pin);
}
6.0 流水燈程序代碼實(shí)現(xiàn)
void LED_StructRun(void)
{LED_No(LED1);DelayNms(1000);LED_No(LED2);DelayNms(1000);LED_No(LED3);DelayNms(1000);LED_Off(LED1);LED_Off(LED2);LED_Off(LED3);DelayNms(1000);
}
8.0 #define 定義LED編號(hào)
#define LED1 0
#define LED2 1
#define LED3 2
9.0 函數(shù)頭文件代碼
#ifndef _LED_STRUCTDRV_H_
#define _LED_STRUCTDRV_H_#include "stdint.h"void LED_DrvInit(void);
// LED_ON 點(diǎn)亮
void LED_No(uint8_t ledNo);
// LED_OFF熄滅
void LED_Off(uint8_t ledNo);
// 流水燈
void LED_StructRun(void);#endif
10.0 主函數(shù)調(diào)用程序
#include <stdint.h>
#include "gd32f30x.h"
#include "led_drv.h"
#include "delay.h"
#include "led_struct_drv.h"int main(void)
{DelayInit();// LED_Init();LED_DrvInit();while(1){// LED_Run();LED_StructRun();}
}
11.0 完整代碼展示
第一種方式完整C函數(shù)代碼
#include "gd32f30x.h" // Device header
#include <stdint.h>
#include "led_drv.h"
#include "delay.h"void LED_Init(void)
{// 開(kāi)啟RCC時(shí)鐘rcu_periph_clock_enable(RCU_GPIOA);rcu_periph_clock_enable(RCU_GPIOE);rcu_periph_clock_enable(RCU_GPIOF);// 初始化gpiogpio_init(GPIOA,GPIO_MODE_OUT_PP,GPIO_OSPEED_2MHZ,GPIO_PIN_8);gpio_init(GPIOE,GPIO_MODE_OUT_PP,GPIO_OSPEED_2MHZ,GPIO_PIN_6);gpio_init(GPIOF,GPIO_MODE_OUT_PP,GPIO_OSPEED_2MHZ,GPIO_PIN_6);// 引腳默認(rèn)電平為低電平gpio_bit_reset(GPIOA, GPIO_PIN_8);gpio_bit_reset(GPIOE, GPIO_PIN_6);gpio_bit_reset(GPIOF, GPIO_PIN_6);
}// 高電平的方式點(diǎn)亮
void LED1_On(void)
{gpio_bit_set(GPIOA, GPIO_PIN_8);
}void LED2_On(void)
{gpio_bit_set(GPIOE, GPIO_PIN_6);
}void LED3_On(void)
{gpio_bit_set(GPIOF, GPIO_PIN_6);
}// 低電平的方式熄滅
void LED1_Off(void)
{gpio_bit_reset(GPIOA, GPIO_PIN_8);
}void LED2_Off(void)
{gpio_bit_reset(GPIOE, GPIO_PIN_6);
}void LED3_Off(void)
{gpio_bit_reset(GPIOF, GPIO_PIN_6);
}// LED 燈流水效果函數(shù)
void LED_Run(void)
{LED1_On();DelayNms(1000);LED2_On();DelayNms(1000);LED3_On();DelayNms(1000);LED1_Off();LED2_Off();LED3_Off();DelayNms(1000);
}
第二種方式完整C函數(shù)代碼
#include "gd32f30x.h" // Device header
#include "stdint.h"
#include "delay.h"#define LED1 0
#define LED2 1
#define LED3 2// 創(chuàng)建結(jié)構(gòu)體
typedef struct
{// rcu時(shí)鐘rcu_periph_enum rcu;// gpio口uint32_t gpio;// 對(duì)應(yīng)引腳uint32_t pin;}LED_GPIO_t;// 計(jì)算數(shù)組大小
#define LED_NUM_MAX (sizeof(g_gpioList) / sizeof(g_gpioList[0]))//創(chuàng)建結(jié)構(gòu)體數(shù)組
static LED_GPIO_t g_gpioList[] =
{{RCU_GPIOA, GPIOA, GPIO_PIN_8},{RCU_GPIOE, GPIOE, GPIO_PIN_6},{RCU_GPIOF, GPIOF, GPIO_PIN_6}
};void LED_DrvInit(void)
{uint8_t i = 0;for(i = 0; i < LED_NUM_MAX; i++){// 開(kāi)啟rcu時(shí)鐘rcu_periph_clock_enable(g_gpioList[i].rcu);// 初始化gpio端口gpio_init(g_gpioList[i].gpio, GPIO_MODE_OUT_PP,GPIO_OSPEED_2MHZ, g_gpioList[i].pin);// 引腳默認(rèn)值gpio_bit_reset(g_gpioList[i].gpio, g_gpioList[i].pin);}}// LED_ON 點(diǎn)亮
void LED_No(uint8_t ledNo)
{// 判斷l(xiāng)ed編號(hào)的值是否大于最大數(shù)組長(zhǎng)度if(ledNo > LED_NUM_MAX){return; // 返回值無(wú)效}// 點(diǎn)亮gpio_bit_set(g_gpioList[ledNo].gpio, g_gpioList[ledNo].pin);
}// LED_OFF熄滅
void LED_Off(uint8_t ledNo)
{if (ledNo >= LED_NUM_MAX){return;}gpio_bit_reset(g_gpioList[ledNo].gpio, g_gpioList[ledNo].pin);
}void LED_StructRun(void)
{LED_No(LED1);DelayNms(1000);LED_No(LED2);DelayNms(1000);LED_No(LED3);DelayNms(1000);LED_Off(LED1);LED_Off(LED2);LED_Off(LED3);DelayNms(1000);
}
12.0 回調(diào)函數(shù)基礎(chǔ)知識(shí)補(bǔ)充
定義:回調(diào)函數(shù)就是一個(gè)通過(guò)函數(shù)指針調(diào)用的函數(shù)。如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個(gè)函數(shù),當(dāng)這個(gè)指針被用來(lái)調(diào)用其所指向的函數(shù)時(shí),我們就說(shuō)這是回調(diào)函數(shù)。
把一段可執(zhí)行的代碼像參數(shù)傳遞那樣傳給其他代碼,而這段代碼會(huì)在某個(gè)時(shí)刻被調(diào)用執(zhí)行,這就叫做回調(diào)。如果代碼立即被執(zhí)行就稱(chēng)為同步回調(diào),如果在之后晚點(diǎn)的某個(gè)時(shí)間再執(zhí)行,則稱(chēng)之為異步回調(diào)
函數(shù) F1 調(diào)用函數(shù) F2 的時(shí)候,函數(shù) F1 通過(guò)參數(shù)給 函數(shù) F2 傳遞了另外一個(gè)函數(shù) F3 的指針,在函數(shù) F2 執(zhí)行的過(guò)程中,函數(shù)F2 調(diào)用了函數(shù) F3,這個(gè)動(dòng)作就叫做回調(diào)(Callback),而先被當(dāng)做指針傳入、后面又被回調(diào)的函數(shù) F3 就是回調(diào)函數(shù)。
以上定義參考自菜鳥(niǎo)教程
#define _CRT_SECURE_NO_WARNINGS
#include <easyx.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>int Sum(int x, int y)
{return x + y;
}// 創(chuàng)建一個(gè)函數(shù),參數(shù)是函數(shù)指針
void Handle(int (*pSum)(int a, int b))
{int sum = (*pSum)(1, 2);printf("%d\n", sum);
}int main() {Handle(Sum);return 0;}
函數(shù)的執(zhí)行結(jié)果是3
typedef 可以對(duì)函數(shù)進(jìn)行重定義,注意這個(gè)時(shí)候的寫(xiě)法是表示的含義還是不同的比如以下的案例
typedef unsigned char uchar; 給變量進(jìn)行從命名,如unsigned char 命名為uchar,
#define _CRT_SECURE_NO_WARNINGS
#include <easyx.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>// 這個(gè)時(shí)候函數(shù)指針變量的名字是 PFUNC
typedef int (*PFUNC)(int a, int b);int Sum(int x, int y)
{return x + y;
}// 創(chuàng)建一個(gè)函數(shù),參數(shù)是函數(shù)指針
void Handle(PFUNC pSum)
{int sum = (*pSum)(1, 2);printf("%d\n", sum);
}int main() {Handle(Sum);return 0;}
以上程序的執(zhí)行結(jié)果也是三
?...
結(jié)尾
目的是通過(guò)本次代碼的編寫(xiě)鞏固之前的知識(shí),同時(shí)使用想把裸機(jī)程序任務(wù)調(diào)度的方式,以及回調(diào)函數(shù)的知識(shí)運(yùn)用在本次的代碼當(dāng)中,方便理解后續(xù)的代碼知識(shí),以上內(nèi)容僅供學(xué)習(xí)參考,后續(xù)后繼續(xù)更細(xì)裸機(jī)任務(wù)調(diào)度方案以及回調(diào)函數(shù)相關(guān)的運(yùn)用。