天天看点

K210学习记录(2)——UART(串口)0、引言1、UART——interrupt2、UART——DMA3、双串口使用参考资料

0、引言

本系列博客仅作为本人学习K210单片机的学习记录,主要学习其内部资源使用,作为初学者难免有错误之处,如有发现还望指出。

硬件:Sipeed Maix Dock开发板(推荐官方KD233开发板)

软件:Kendryte IDE(基于VS Code 开发)

文档:

Kendryte IDE使用手册

Standalone SDK编程指南

芯片技术规格书

SDK:

Kendryte SDK

MaixPy/drive

K210学习记录(2)——UART(串口)0、引言1、UART——interrupt2、UART——DMA3、双串口使用参考资料

1、UART——interrupt

以下代码为官方代码库“kendryte_uart-interrupt-standalone”修改而成,实现的功能为将电脑发送的字符串,在中断回调函数中存入缓存v_buf中,字符串接收完成后,再将v_buf中的数据上传回电脑。管脚配置如下所示

K210学习记录(2)——UART(串口)0、引言1、UART——interrupt2、UART——DMA3、双串口使用参考资料

main.c

#include <fpioa.h>
#include <gpio.h>
#include <stdio.h>
#include <string.h>
#include <sysctl.h>
#include <uart.h>


//UART_NUM位于uart.h中 ,用于定义所使用的串口号
//#define UART_NUM UART_DEVICE_3
uint32_t v_uart_num = UART_NUM;

//打印字符串,通过指针
void uart_print(const char const *str) {
  uart_send_data(UART_NUM, str, strlen(str));
}

//发送中断回调函数(想不到用途)
int on_uart_send(void *ctx) {
  uint8_t v_uart = *((uint32_t *)ctx) + 1 + 0x30;
  //注销中断函数,保证该功能单次使用,否则会陷入局部死循环。
  uart_irq_unregister(UART_NUM, UART_SEND);

  uart_print("Send ok Uart\n");                  //测试用
  uart_send_data(UART_NUM, (char *)&v_uart, 1);  //标准发送程序,位于uart.c
  return 0;
}

int main() {
  plic_init();//中断初始化
  sysctl_enable_irq();//开启系统中断
  uart_init(UART_NUM); //初始化配置串口。通道3
  uart_configure(UART_NUM, 115200, 8, UART_STOP_1, UART_PARITY_NONE);
  //接收中断或 DMA 触发 FIFO 深度,当 FIFO 中的数据大于等于该值时触发中断或 DMA传输。
  uart_set_receive_trigger(UART_NUM, UART_RECEIVE_FIFO_8);
  //串口中断配置(通道、接收中断、回调函数)
  uart_irq_register(UART_NUM, UART_RECEIVE, on_uart_recv, NULL, 2);

  //发送中断配置
  // uart_set_send_trigger(UART_NUM, UART_SEND_FIFO_0);
  //当发送事件产生,触发中断及回调函数(想不到用途)
  //  uart_irq_register(UART_NUM, UART_SEND, on_uart_send, &v_uart_num, 2);
  //发送字符串
  char *hel = {"hello world!\n"};
  uart_send_data(UART_NUM, hel, strlen(hel));

  while (1) {
    if (uart_recv_ztj) //当字符串接收完成,uart_recv_ztj置高
    {
      uart_send_data(UART_NUM, v_buf, uart_recv_len);//将收到的数据发送回去
      uart_recv_ztj = 0;//清除标志位
    }
  }
}
           

uart.h(其他部分与官方提供的库一致,后文不再赘述)

#define BUF_LEN 200//定义接收最大长度
#define UART_NUM UART_DEVICE_3//定义使用的通道
extern char v_buf[BUF_LEN];//将缓存配置位全局变量
extern char uart_recv_ztj;  //接收数据状态机
extern int uart_recv_len;   //实际接收到的数据长度

void on_uart_recv(void);//中断函数,需要在uart_irq_register中配置
           

uart.c(可根据自己实际的报文格式,对代码进行二次修改)

char v_buf[BUF_LEN];     //接收数据缓冲区
char uart_recv_ztj = 0;  //接收状态机
int uart_recv_len = 0;//实际长度

//接收中断回调参数,处理接收数据
void on_uart_recv(void) {
  size_t i = 0;
  for (i = 0; i < BUF_LEN; i++) {
  //以下两行为官方所采用判断是否接收完成的代码,不完全理解其含义
    if (uart[UART_DEVICE_3]->LSR & 1)
      v_buf[i] = (char)(uart[UART_DEVICE_3]->RBR & 0xff);
    else {
      uart_recv_ztj = 1;  //接收完成
      uart_recv_len = i;  //将真实长度传递
      break;//跳出循环
    }
  }
}
           

测试结果如下所示

K210学习记录(2)——UART(串口)0、引言1、UART——interrupt2、UART——DMA3、双串口使用参考资料

详情请参考 《Standalone SDK编程指南》——通用异步收发传输器 (UART)部分

2、UART——DMA

使用串口接收触发中断,后调用DMA收数据,再将数据发出去,其他函数看了很久,没弄得明白,在此不表。

#include <fpioa.h>
#include <gpio.h>
#include <stdio.h>
#include <string.h>
#include <sysctl.h>
#include <uart.h>

//回调函数
void ztj() {
  uart_receive_data_dma(UART_NUM, DMAC_CHANNEL1, v_buf, 10);//将数据通过DMA方式接收
  uart_send_data_dma(UART_NUM, DMAC_CHANNEL0, v_buf, 10);
}

int main() {
  dmac_init();
  plic_init();          //中断初始化
  sysctl_enable_irq();  //开启系统中断

  gpio_init();                             //初始化GPIO
  gpio_set_drive_mode(0, GPIO_DM_OUTPUT);  //将GPIO 0配置为输出模型
  gpio_set_pin(0, GPIO_PV_HIGH);           // GPIO 0 输出高

  //初始化配置串口。通道3
  uart_init(UART_NUM);
  uart_configure(UART_NUM, 115200, 8, UART_STOP_1, UART_PARITY_NONE);
  //接收中断或 DMA 触发 FIFO 深度,当 FIFO 中的数据大于等于该值时触发中断或
  // DMA传输。
  // uart_set_receive_trigger(UART_NUM, UART_RECEIVE_FIFO_8);
  //串口中断配置(通道、接收中断、回调函数)
  uart_irq_register(UART_NUM, UART_RECEIVE, ztj, NULL, 1);

  //发送字符串
  char *hel = {"hello world!\n"};
  // uart_send_data(UART_NUM, hel, strlen(hel));
  uart_send_data_dma(UART_NUM, DMAC_CHANNEL0, hel, strlen(hel));
  while (1) {
    gpio_set_pin(0, 1);
    msleep(2000);
    gpio_set_pin(0, 0);
    msleep(2000);
  }
}
           

3、双串口使用

FPIOA很大程度方便了硬件设计,将GPIO 34/35 配置为UART1 RX/TX,GPIO 4/5 配置为UART3 RX/TX。

关于两个串口的配置也相对简单,再库函数中修改为对应的串口信道即可,详情见代码。

程序流程:使用UART3中断来接收PC下发的字符串,接收完成后用UART1再发送回PC。

K210学习记录(2)——UART(串口)0、引言1、UART——interrupt2、UART——DMA3、双串口使用参考资料
K210学习记录(2)——UART(串口)0、引言1、UART——interrupt2、UART——DMA3、双串口使用参考资料

main.c

#include <fpioa.h>
#include <gpio.h>
#include <stdio.h>
#include <string.h>
#include <sysctl.h>
#include <uart.h>

int main() {
  plic_init();          //中断初始化
  sysctl_enable_irq();  //开启系统中断

  gpio_init();                             //初始化GPIO
  gpio_set_drive_mode(0, GPIO_DM_OUTPUT);  //将GPIO 0配置为输出模型
  gpio_set_pin(0, GPIO_PV_HIGH);           // GPIO 0 输出高

  uart_init(UART_NUM);  //初始化配置串口。通道3
  uart_configure(UART_NUM, 115200, 8, UART_STOP_1, UART_PARITY_NONE);

    uart_init(UART_DEVICE_1);  //初始化配置串口。通道1
  uart_configure(UART_DEVICE_1, 115200, 8, UART_STOP_1, UART_PARITY_NONE);
  //接收中断或 DMA 触发 FIFO 深度,当 FIFO 中的数据大于等于该值时触发中断或
  //DMA传输。 uart_set_receive_trigger(UART_NUM, UART_RECEIVE_FIFO_8);
  //串口中断配置(通道、接收中断、回调函数)
  uart_irq_register(UART_NUM, UART_RECEIVE, on_uart_recv, NULL, 2);

  //发送中断配置
  // uart_set_send_trigger(UART_NUM, UART_SEND_FIFO_0);
  //当发送事件产生,触发中断及回调函数(想不到用途)
  //  uart_irq_register(UART_NUM, UART_SEND, on_uart_send, &v_uart_num, 2);
  //发送字符串
  char *hel = {"hello world!\n"};
  uart_send_data(UART_NUM, hel, strlen(hel));

  while (1) {
    gpio_set_pin(0, 1);
    msleep(2000);
    gpio_set_pin(0, 0);
    msleep(2000);
  }
}
           

uart.c

//接收中断回调参数,处理接收数据
void on_uart_recv(void) {
  size_t i = 0;
  for (i = 0; i < BUF_LEN; i++) {
    if (uart[UART_DEVICE_3]->LSR & 1)
      v_buf[i] = (char)(uart[UART_DEVICE_3]->RBR & 0xff);
    else {
      uart_recv_ztj = 1;  //接收完成
      uart_recv_len = i;  //将真实长度传递
      //uart_send_data(UART_NUM, v_buf, uart_recv_len);
      break;
    }
  }

  if (uart_recv_ztj)  //当字符串接收完成,uart_recv_ztj置高
  {
    // uart_send_data(UART_NUM, v_buf, uart_recv_len);  //将收到的数据发送回去
    uart_send_data_dma(UART_DEVICE_1, DMAC_CHANNEL0, v_buf, uart_recv_len);//使用DMA发送数据
    uart_recv_ztj = 0;  //清除标志位
  }
}
           

测试结果

K210学习记录(2)——UART(串口)0、引言1、UART——interrupt2、UART——DMA3、双串口使用参考资料

参考资料

《Kendryte IDE使用手册》

《Standalone SDK编程指南》

《芯片技术规格书》

K210学习记录(1)——GPIO与软件使用

继续阅读