单片机
返回首页

K210学习记录(2)——UART(串口)

2022-07-01 来源:csdn

0、引言

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


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

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


文档:

Kendryte IDE使用手册

Standalone SDK编程指南


芯片技术规格书

SDK:

Kendryte SDK

MaixPy/drive


1、UART——interrupt

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

main.c


#include

#include

#include

#include

#include

#include


//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 Uartn');                  //测试用

  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;//跳出循环

    }

  }

}


测试结果如下所示

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


2、UART——DMA

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


#include

#include

#include

#include

#include

#include


//回调函数

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。

main.c


#include

#include

#include

#include

#include

#include


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;  //清除标志位

  }

}


测试结果

在这里插入图片描述

参考资料

《Kendryte IDE使用手册》


《Standalone SDK编程指南》


《芯片技术规格书》


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 用数字电路CD4069制作的万能遥控轻触开关

  • 红外线探测报警器

  • 短波AM发射器电路设计图

  • RS-485基础知识:处理空闲总线条件的两种常见方法

  • 带有短路保护系统的5V直流稳压电源电路图

  • 基于ICL296的大电流开关稳压器电源电路

    相关电子头条文章