K210应用5-使用中断方式通过UART接收数据

使用中断方式通过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深度。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
K210是一款由中国芯片设计公司寒武纪(Kendryte)推出的低功耗、高性能的人工智能处理器。它具有强大的计算能力和丰富的外设接口,适用于物联网、机器人、智能家居等领域的开发。 在K210使用Python进行串口中断编程,可以通过使用`machine.UART`模块来实现。下面是一个简单的示例代码: ```python import machine def uart_interrupt_handler(uart): # 处理串口中断事件的回调函数 if uart.any(): data = uart.read() # 处理接收到的数据 print("Received data:", data) # 初始化串口对象 uart = machine.UART(1, baudrate=115200, rx=8, tx=9) # 设置串口中断回调函数 uart.irq(handler=uart_interrupt_handler, trigger=machine.UART.RXNE) # 主循环 while True: pass ``` 在上述代码中,我们首先导入了`machine`模块,然后定义了一个名为`uart_interrupt_handler`的回调函数,用于处理串口中断事件。在回调函数中,我们通过`uart.any()`方法检查是否有数据可读,如果有则使用`uart.read()`方法读取数据,并进行相应的处理。 接下来,我们创建了一个`UART`对象,并通过指定参数来初始化串口,包括波特率、接收引脚和发送引脚。然后,我们使用`uart.irq()`方法设置了串口中断的回调函数和触发条件,这里我们选择了接收缓冲区非空时触发中断。 最后,我们进入主循环,通过`while True`保持程序的运行,等待串口中断事件的发生。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tigalight

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值