歡迎回到我們的RA系列FSP庫(kù)開(kāi)發(fā)實(shí)戰(zhàn)指南頻道,下面我們將繼續(xù)講解“自己寫(xiě)庫(kù)——構(gòu)建庫(kù)函數(shù)雛形”部分??:
定義IO初始化結(jié)構(gòu)體
由上述IOPORT相關(guān)功能的枚舉類(lèi)型我們可以知道,在對(duì)IOPORT模塊進(jìn)行初始化時(shí)需要根據(jù)情況配置它們。因此我們定義一個(gè)IOPORT初始化的結(jié)構(gòu)體類(lèi)型IOPORT_Init_t,它的成員包括了由上述所有枚舉類(lèi)型所聲明的變量,因此該結(jié)構(gòu)體類(lèi)型的變量可以包含IOPORT的相關(guān)功能配置。
列表5:代碼清單8-4:ra_ioport.h文件
/* IOPORT 初始化結(jié)構(gòu)體類(lèi)型定義 */typedefstruct{IO_Port_t Port;IO_Pin_t Pin;IO_Mode_t Mode;IO_Dir_t Dir;IO_OType_t OType;IO_DriveCapability_t Drive;IO_Level_t Level;IO_Pull_t Pull;} IOPORT_Init_t;
編寫(xiě)IO操作函數(shù)
我們把IO操作函數(shù)的聲明和IO初始化函數(shù)的聲明都放在ra_ioport.h頭文件。
列表6:代碼清單8-5:ra_ioport.h文件
/* IO 操作函數(shù)(調(diào)用一次只能操作一個(gè) IO 引腳) */uint32_tIOPORT_PinRead(IO_Port_t port, IO_Pin_t pin);voidIOPORT_PinWrite(IO_Port_t port, IO_Pin_t pin, IO_Level_t?→level);voidIOPORT_PinToggle(IO_Port_t port, IO_Pin_t pin);voidIOPORT_PinAccessEnable(void);voidIOPORT_PinAccessDisable(void);/* IO 初始化函數(shù)(調(diào)用一次只能初始化一個(gè) IO 引腳) */voidIOPORT_Init(IOPORT_Init_t *ioport_init);
然后在ra_ioport.c源文件里面實(shí)現(xiàn)這些IO操作函數(shù)。
列表7:代碼清單8-6:ra6m5_ioport.c文件
/* 讀引腳電平 */uint32_tIOPORT_PinRead(IO_Port_t port, IO_Pin_t pin){/* Read pin level. */return R_PFS->PORT[port >> 8].PIN[pin].PmnPFS_b.PIDR;}/* 寫(xiě)引腳電平 */voidIOPORT_PinWrite(IO_Port_t port, IO_Pin_t pin, IO_Level_t level){uint32_t pfs_bits = R_PFS->PORT[port >> 8].PIN[pin].PmnPFS; //讀寄存器?→PmnPFSpfs_bits &= ~(uint32_t)0x1; //清零 PODR 位R_PFS->PORT[port >> 8].PIN[pin].PmnPFS = (pfs_bits | level);}/* 翻轉(zhuǎn)引腳電平 */voidIOPORT_PinToggle(IO_Port_t port, IO_Pin_t pin){uint32_t pfs_bits = R_PFS->PORT[port >> 8].PIN[pin].PmnPFS; //讀寄存器?→PmnPFSpfs_bits ^= (uint32_t)0x1; //取反 PODR 位R_PFS->PORT[port >> 8].PIN[pin].PmnPFS = pfs_bits;}/* 引腳訪問(wèn)使能 */voidIOPORT_PinAccessEnable(void){R_PMISC->PWPR = 0; ///< Clear BOWI bit - writing to PFSWE bit?→enabledR_PMISC->PWPR = 1U << 6U; ///< Set PFSWE bit - writing to PFS register?→enabled}/* 引腳訪問(wèn)禁止 */voidIOPORT_PinAccessDisable(void){R_PMISC->PWPR = 0; ///< Clear PFSWE bit - writing to PFS register?→disabledR_PMISC->PWPR = 1U << 7U; ///< Set BOWI bit - writing to PFSWE bit?→disabled}
編寫(xiě)IO初始化函數(shù)
最后編寫(xiě)IOPORT初始化函數(shù)。
列表8:代碼清單8-7:ra_ioport.c文件
/* IOPORT 初始化函數(shù) */voidIOPORT_Init(IOPORT_Init_t *ioport_init){uint32_t pfs_bits = 0; //不讀取寄存器 PmnPFSif(ioport_init->Mode == IO_MODE_GPIO) //如果引腳用作普通 GPIO 功能{if(ioport_init->Dir == IO_DIR_INPUT) /* 用作輸入模式 */{pfs_bits |= (ioport_init->Pull) << 4; //設(shè)置輸入上拉}elseif(ioport_init->Dir == IO_DIR_OUTPUT) /* 用作輸出模式 */{pfs_bits |= (ioport_init->Dir) << 2; //設(shè)置為輸出pfs_bits |= (ioport_init->Level) << 0; //設(shè)置輸出電平pfs_bits |= (ioport_init->Mode) << 6; //設(shè)置輸出模式pfs_bits |= (ioport_init->Drive) << 10; //設(shè)置輸出驅(qū)動(dòng)能力}}else{//我們不考慮引腳用作復(fù)用模式和模擬輸入輸出模式的情況//也不考慮中斷的情況,僅考慮普通的 GPIO 輸入輸出功能}/* 寫(xiě)入配置到寄存器 PmnPFS */R_PFS->PORT[ioport_init->Port >> 8].PIN[ioport_init->Pin].PmnPFS = pfs_→bits;}
hal_entry入口函數(shù)
前一章節(jié)實(shí)驗(yàn)里有講過(guò),當(dāng)使用RTOS時(shí),程序從main函數(shù)開(kāi)始進(jìn)行線程調(diào)度;當(dāng)沒(méi)有使用RTOS時(shí),C語(yǔ)言程序的入口函數(shù)main函數(shù)調(diào)用了hal_entry函數(shù)。本章節(jié)實(shí)驗(yàn)的工程也是沒(méi)有選用RTOS的,因此,用戶(hù)程序是從hal_entry函數(shù)開(kāi)始執(zhí)行。
打開(kāi)“\src\hal_entry.c”文件,我們?cè)凇癶al_entry.c”文件中添加對(duì)頭文件“ra_ioport.h”的包含,然后在hal_entry函數(shù)里面編寫(xiě)我們的代碼。
以啟明6M5開(kāi)發(fā)板為例,RA6M5工程的hal_entry數(shù)代碼如下所示。
注解
啟明4M2開(kāi)發(fā)板和啟明2L1開(kāi)發(fā)板的用戶(hù)可直接打開(kāi)配套的“09_Register_MyLib”例程查看該代碼,限于篇幅,不在本章中貼出。
列表9:代碼清單8-8:hal_entry.c文件
/* IOPORT 模塊頭文件 (自己寫(xiě)庫(kù)——構(gòu)建庫(kù)函數(shù)雛形) */voidhal_entry(void){/* TODO: add your own code here *//* 調(diào)用取消寫(xiě)保護(hù)函數(shù) */IOPORT_PinAccessEnable();/* 使用 IOPORT 初始化結(jié)構(gòu)體和調(diào)用初始化函數(shù)來(lái)配置 PFS 寄存器 */IOPORT_Init_t led_io_init;led_io_init.Port = IO_PORT_04;led_io_init.Pin = IO_PIN_00;led_io_init.Mode = IO_MODE_GPIO; //普通 GPIO 模式,而不是復(fù)用功能模式或其他的led_io_init.Dir = IO_DIR_OUTPUT;led_io_init.OType = IO_OTYPE_PP;led_io_init.Drive = IO_DRIVE_LOW;led_io_init.Level = IO_LEVEL_HIGH; //輸出高電平(LED 熄滅)//LED_IO_Init.Pull = IO_NO_PULL; //端口方向處于輸出模式下是用不了上拉的,所以這個(gè)屬性沒(méi)意義IOPORT_Init(&led_io_init); //調(diào)用初始化函數(shù),進(jìn)行 LED1 引腳初始化led_io_init.Pin = IO_PIN_03; //更換引腳號(hào)IOPORT_Init(&led_io_init); //結(jié)構(gòu)體其他屬性不變,再次調(diào)用初始化函數(shù),進(jìn)行 LED2 引腳初始化led_io_init.Pin = IO_PIN_04; //更換引腳號(hào)IOPORT_Init(&led_io_init); //結(jié)構(gòu)體其他屬性不變,再次調(diào)用初始化函數(shù),進(jìn)行 LED3 引腳初始化/** 此時(shí) 3 個(gè) LED 燈的引腳默認(rèn)輸出的是高電平,所以 3 個(gè) LED 燈都會(huì)默認(rèn)不亮* 我們先打開(kāi)所有 LED 燈,然后在 while 循環(huán)里讓 LED1 閃爍:每秒鐘翻轉(zhuǎn)一次狀態(tài)*/IOPORT_PinWrite(IO_PORT_04, IO_PIN_00, IO_LEVEL_LOW); //點(diǎn)亮 LED1IOPORT_PinWrite(IO_PORT_04, IO_PIN_03, IO_LEVEL_LOW); //點(diǎn)亮 LED2IOPORT_PinWrite(IO_PORT_04, IO_PIN_04, IO_LEVEL_LOW); //點(diǎn)亮 LED3while(1){/* 使用函數(shù) IOPORT_PinToggle 翻轉(zhuǎn) LED1 引腳電平 */IOPORT_PinToggle(IO_PORT_04, IO_PIN_00);R_BSP_SoftwareDelay(1000, BSP_DELAY_UNITS_MILLISECONDS);}/* Enter non-secure code */R_BSP_NonSecureEnter();}
下載驗(yàn)證
編寫(xiě)好上述代碼,然后將程序編譯并下載到開(kāi)發(fā)板之后,按下復(fù)位按鍵來(lái)復(fù)位開(kāi)發(fā)板,可以觀察到實(shí)驗(yàn)現(xiàn)象與上一章的實(shí)驗(yàn)現(xiàn)象相同:開(kāi)發(fā)板上面除了電源指示燈之外的3個(gè)LED燈當(dāng)中有兩個(gè)燈常亮,還有一個(gè)燈在緩慢閃爍。閃爍著的LED燈為L(zhǎng)ED1,它每秒鐘(1000毫秒)便改變一次亮滅的狀態(tài)。

如您在使用瑞薩MCU/MPU產(chǎn)品中有任何問(wèn)題,可識(shí)別下方二維碼或復(fù)制網(wǎng)址到瀏覽器中打開(kāi),進(jìn)入瑞薩技術(shù)論壇尋找答案或獲取在線技術(shù)支持。
https://community-ja.renesas.com/zh/forums-groups/mcu-mpu/
未完待續(xù)
推薦閱讀
自己寫(xiě)庫(kù):構(gòu)建庫(kù)函數(shù)雛形——瑞薩RA系列FSP庫(kù)開(kāi)發(fā)實(shí)戰(zhàn)指南(20)
實(shí)驗(yàn):使用寄存器點(diǎn)亮LED燈——瑞薩RA系列FSP庫(kù)開(kāi)發(fā)實(shí)戰(zhàn)指南(19)
獲獎(jiǎng)公布 | 功能安全系列活動(dòng)獲獎(jiǎng)名單出爐(第二期)

