使用中斷方式通過UART接收資料
- 實驗目的
本節實驗目的為實作串口發送和接收,這一節計劃采取中斷的方式來實作串口接收,K210串口接收到0x00,則熄滅前節提到的紅色LED燈,并通過串口列印Red Led Off,否則,則點亮前節提到的紅色LED燈,并通過串口列印Red Led On,
- 實驗準備
1)、帶UART和發光二極管(LED)的K210開發板一塊,用于實踐并查看實驗現象;
2)、官方裸機編程指導手冊:kendryte_standalone_programming_guide,用于查閱SDK中介面說明,
- 實驗原理
串口通信是指外設和計算機間,通過資料線、地線和控制線等,按位進行資料傳輸的一種通信方式,傳輸方式為一個字符一個字符的傳輸,每個字符一位一位的傳輸,先傳輸低位,再傳輸高位,并且傳輸每個字符時,總是以起始位開始,以停止位結束,位于位之間可根據自己需求,設定時間間隔,這個時間間隔對應波特率;而對于有些場景,為了保證資料的可靠性,還需加上校驗位,稱之為奇偶校驗位,以此來校驗傳輸資料的正確性,如果兩臺設備之間需要通過串口進行通信,上面提到的波特率、資料位、停止位和奇偶校驗位等這些必要引數,必須設定一致,才能進行串口通信,另外,串口通信支持全雙工通信,即:使用一根資料線發送資料的同時,可以用另一個資料線進行資料接收,
- 硬體設計
硬體電路圖如下:


- 軟體設計
軟體流程圖如下:

- 軟體實作
根據硬體設計和軟體設計可知,本節應用實作步驟如下:
1)、設定引腳復用功能:由硬體原理圖可知:我們需要將IO12設定為GPIOHS功能,IO4和IO5設定為UART的RX和TX功能,如下圖:

2)、LED初始化,如下圖:

3)、UART初始化,如下圖:

4)、實作uart3接收中斷回呼函式,在接收中斷回呼函式中,實作串口接收和記錄接收資料長度,如下圖:

5)、通過UART發送提示資訊,如下圖:
![]()
6)、判斷是否接收到資料,如果接收到資料,判斷接收到的控制命令型別,根據接收到的控制命令,進行相應的操作,如下圖:

根據上述實作步驟,最終代碼如下:
#include <fpioa.h>
#include <gpiohs.h>
#include <uart.h>
#include <plic.h>
#include <sysctl.h>
#include <stdio.h>
#include <sleep.h>
#define LED_R_PIN (12)
#define LED_R_GPIOHSNUM (0)
#define LED_R_FUNC (FUNC_GPIOHS0+LED_R_GPIOHSNUM)
#define UART3_RX_PIN (4)
#define UART3_TX_PIN (5)
#define UART3_NUM (UART_DEVICE_3)
#define UART3_RX_FUNC (FUNC_UART1_RX+UART3_NUM*2)
#define UART3_TX_FUNC (FUNC_UART1_TX+UART3_NUM*2)
/*********************************
* 管腳功能初始化
********************************/
void init_hardware(void)
{
// 將紅色LED管腳設定復用為GPIOHS
fpioa_set_function(LED_R_PIN, LED_R_FUNC);
// 將UART管腳設定復用為UART
fpioa_set_function(UART3_RX_PIN, UART3_RX_FUNC);
fpioa_set_function(UART3_TX_PIN, UART3_TX_FUNC);
}
/*********************************
* LED初始化
********************************/
void init_led(gpio_pin_value_t value)
{
// 設定輸出
gpiohs_set_drive_mode(LED_R_GPIOHSNUM, GPIO_DM_OUTPUT);
// 設定初始電平狀態
gpiohs_set_pin(LED_R_GPIOHSNUM, value);
}
/*********************************
* 控制LED亮滅
********************************/
void ctl_led(gpio_pin_value_t value)
{
gpiohs_set_pin(LED_R_GPIOHSNUM, value);
}
struct RCVBUF {
char buf[128];
unsigned char len;
};
/*********************************
* UART接收中斷回呼函式
********************************/
int irq_uart3_rcv(void *ctx)
{
struct RCVBUF *rcv_buf = (struct RCVBUF *)ctx;
rcv_buf->len = uart_receive_data(UART3_NUM, rcv_buf->buf, 1);
return 0;
}
/*********************************
* UART初始化
********************************/
void init_uart(struct RCVBUF *rcv_buf)
{
// 初始化 uart
uart_init(UART3_NUM);
// 設定 uart 作業模式
uart_set_work_mode (UART3_NUM , UART_NORMAL);
// 設定 UART 相關引數
uart_config (UART3_NUM , 115200 , UART_BITWIDTH_8BIT , UART_STOP_1 , UART_PARITY_NONE);
// 初始化外部中斷
plic_init();
// 注冊 UART 中斷函式
uart_irq_register (UART3_NUM, UART_RECEIVE, irq_uart3_rcv, rcv_buf , 1);
// 設定接收中斷 觸發 FIFO 深度
uart_set_receive_trigger(UART3_NUM, UART_RECEIVE_FIFO_1);
// 使能系統中斷,如果使用中斷,一定要開啟系統中斷
sysctl_enable_irq();
}
int main(int argc, char **argv)
{
init_hardware();
init_led(GPIO_PV_HIGH);
struct RCVBUF rcv_buf = {
.len = 0,
};
init_uart(&rcv_buf);
uart_send_data(UART3_NUM, "CTL LED:[0:OFF/1:ON] \r\n", sizeof("CTL LED:[0:OFF/1:ON] \r\n"));
while (1)
{
if(rcv_buf.len != 0)
{
uart_send_data(UART3_NUM, "rcv_buf.len:", sizeof("rcv_buf.len:"));
uart_send_data(UART3_NUM, (char *)&rcv_buf.len, sizeof(rcv_buf.len));
if(rcv_buf.buf[0] == 0)
{
uart_send_data(UART3_NUM, "LER_R OFF! \r\n", sizeof("LER_R OFF! \r\n"));
ctl_led(GPIO_PV_HIGH);
}
else
{
uart_send_data(UART3_NUM, "LER_R ON! \r\n", sizeof("LER_R ON! \r\n"));
ctl_led(GPIO_PV_LOW);
}
uart_send_data(UART3_NUM, "CTL LED:[0:OFF/1:ON] \r\n", sizeof("CTL LED:[0:OFF/1:ON] \r\n"));
rcv_buf.len = 0;
}
usleep(20000);
}
return 0;
}
- 編譯
1)、同上一節類似,在SDK中創建uart_irq檔案夾,在新建的檔案夾中創建一個main.c檔案,然后將本節代碼輸入到main.c檔案中,如下圖:

2)、同上一節的編譯方式類似,打開vscode終端,在終端中進入上一節創建的build檔案夾,然后輸入:cmake ../ -DPROJ=uart_irq -G "MinGW Makefiles" ,生成makefile檔案,如下圖:

3)、生成makefile檔案后,輸入:make ,開始編譯,如下圖:

4)、編譯完成后,會在build目錄下生成燒錄檔案:uart_irq.bin,如下圖:

- 燒錄
同上一節的燒錄方式類似,注意:Firmware那一項選擇我們剛編譯出的uart_irq.bin檔案,
- 實驗現象
通過串口助手,發送0x00,紅色LED燈熄滅,發送其他非零數,紅色LED亮起,如下圖:
1)、開啟LED

2)、關閉LED

- 實驗總結
1)、K210串口中斷有接收中斷和發送中斷,用戶可根據需求設定想要的中斷方式;
2)、K210串口的中斷可設定觸發FIFO深度,用戶可根據需求設定想要的FIFO深度,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/357199.html
標籤:其他
上一篇:有關hc-12的使用經驗
