k210开发板 K210_Kendryte 串口中断
通过Kendryte开发平台,实现k210开发板的串口中断,串口助手发送55 AA 55 55 55 55 led灯亮,发送55 AA AA AA AA AAled灯灭,我使用的是01Studio的开发板,配置了三色灯的蓝灯IO12.
#include <stdio.h>
#include <string.h>
#include "fpioa.h"
#include "gpiohs.h"
#include "sysctl.h"
#include "uart.h"
#define CMD_LENTH 4
#define CLOSLIGHT 0x55555555
#define OPENLIGHT 0xAAAAAAAA
#define UART_NUM UART_DEVICE_3
int release_cmd(char *cmd) { //串口命令执行函数
switch (*((int *)cmd)) {
case CLOSLIGHT:
gpiohs_set_pin(3, GPIO_PV_LOW);
break;
case OPENLIGHT:
gpiohs_set_pin(3, GPIO_PV_HIGH);
break;
}
return 0;
}
///发送函数
int on_uart_send(void *ctx) {
uint8_t v_uart = *((uint32_t *)ctx) + 1 + 0x30; //2+1为串口3,0x30转为ASCII
uart_irq_unregister(UART_NUM, UART_SEND);
char *v_send_ok = "Send ok Uart";
uart_send_data(UART_NUM, v_send_ok, strlen(v_send_ok));
uart_send_data(UART_NUM, (char *)&v_uart, 1); //发送串口号
return 0;
}
volatile uint32_t recv_flag = 0;
char g_cmd[4];
volatile uint8_t g_cmd_cnt = 0;
//接受函数中断
int on_uart_recv(void *ctx) {
char v_buf[8];
int ret = uart_receive_data(UART_NUM, v_buf, 8);
for (uint32_t i = 0; i < ret; i++) {
if (v_buf[i] == 0x55 && (recv_flag == 0 || recv_flag == 1)) { //第一个字节匹配
recv_flag = 1;
continue;
} else if (v_buf[i] == 0xAA && recv_flag == 1) {//第二个字节匹配
recv_flag = 2;
g_cmd_cnt = 0;
continue;
} else if (recv_flag == 2 && g_cmd_cnt < CMD_LENTH) {//获取控制命令四个字节
g_cmd[g_cmd_cnt++] = v_buf[i];
if (g_cmd_cnt >= CMD_LENTH) {
release_cmd(g_cmd);
recv_flag = 0;
}
continue;
} else {
recv_flag = 0;
}
}
return 0;
}
void io_mux_init(void) {
fpioa_set_function(4, FUNC_UART1_RX + UART_NUM * 2); //串口接收
fpioa_set_function(5, FUNC_UART1_TX + UART_NUM * 2); //串口发送
fpioa_set_function(12, FUNC_GPIOHS3); // led
}
int main() {
io_mux_init(); //串口引脚配置
plic_init(); //中断初始化
sysctl_enable_irq(); //使能中断
gpiohs_set_drive_mode(3, GPIO_DM_OUTPUT); // led初始化
gpio_pin_value_t value = GPIO_PV_HIGH;
gpiohs_set_pin(3, value);
uart_init(UART_NUM); //串口初始化
uart_configure(UART_NUM, 115200, 8, UART_STOP_1, UART_PARITY_NONE);
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); //发送中断
uint32_t v_uart_num = UART_NUM;
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)
;
}
/////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////uart dma发送接收
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "fpioa.h"
#include "gpiohs.h"
#include "sysctl.h"
#include "uart.h"
#define CMD_LENTH 4
#define CLOSLIGHT 0x55555555
#define OPENLIGHT 0xAAAAAAAA
#define UART_NUM UART_DEVICE_1
uint32_t recv_buf[48];
#define RECV_DMA_LENTH 6
volatile uint32_t recv_flag = 0;
char g_cmd[4];
volatile uint8_t g_cmd_cnt = 0;
int release_cmd(char *cmd)
{
switch (*((int *)cmd)) {
case CLOSLIGHT:
gpiohs_set_pin(3, GPIO_PV_LOW);
break;
case OPENLIGHT:
gpiohs_set_pin(3, GPIO_PV_HIGH);
break;
}
return 0;
}
volatile uint32_t g_uart_send_flag = 0;
int uart_send_done(void *ctx) //发送完成
{
g_uart_send_flag = 1;
return 0;
}
int uart_recv_done(void *ctx) //接受完成
{
uint32_t *v_dest = ((uint32_t *)ctx) + RECV_DMA_LENTH;
if (v_dest >= recv_buf + 48) v_dest = recv_buf;
uart_data_t data = (uart_data_t) //重新初始化dma接收中断
{
.rx_channel = DMAC_CHANNEL1,
.rx_buf = v_dest,
.rx_len = RECV_DMA_LENTH,
.transfer_mode = UART_RECEIVE,
};
plic_interrupt_t irq = (plic_interrupt_t){
.callback = uart_recv_done,
.ctx = v_dest,
.priority = 2,
};
uart_handle_data_dma(UART_NUM, data, &irq);
uint32_t *v_buf = (uint32_t *)ctx;
for (uint32_t i = 0; i < RECV_DMA_LENTH; i++) {
if (v_buf[i] == 0x55 && (recv_flag == 0 || recv_flag == 1)) {
recv_flag = 1;
continue;
} else if (v_buf[i] == 0xAA && recv_flag == 1) {
recv_flag = 2;
g_cmd_cnt = 0;
continue;
}
else if (recv_flag == 2 && g_cmd_cnt < CMD_LENTH) {
g_cmd[g_cmd_cnt++] = v_buf[i];
if (g_cmd_cnt >= CMD_LENTH) {
release_cmd(g_cmd);
recv_flag = 0;
}
continue;
}
else {
recv_flag = 0;
}
}
return 0;
}
void io_mux_init(void) //串口引脚配置
{
fpioa_set_function(4, FUNC_UART1_RX + UART_NUM * 2);
fpioa_set_function(5, FUNC_UART1_TX + UART_NUM * 2);
fpioa_set_function(12, FUNC_GPIOHS3); // led
}
int main(void) {
io_mux_init(); //串口引脚配置
dmac_init(); //直接内存访问
plic_init(); //中断
sysctl_enable_irq(); //中断使能
gpiohs_set_drive_mode(3, GPIO_DM_OUTPUT); // led初始化为高电平
gpiohs_set_pin(3, GPIO_PV_HIGH);
uart_init(UART_NUM); //串口初始化
uart_configure(UART_NUM, 115200, 8, UART_STOP_1,
UART_PARITY_NONE); //设置波特率,数据位,停止位,奇偶校验
uint8_t *hel = {"hello!\n"};
uint32_t *v_tx_buf = malloc(sizeof(hel) * sizeof(uint32_t)); //申请内存
for (uint32_t i = 0; i < strlen(hel); i++) //存放字符串
{
v_tx_buf[i] = hel[i];
}
uart_data_t data = (uart_data_t) //创建结构体发送dma
{
.tx_channel = DMAC_CHANNEL0, //通道
.tx_buf = v_tx_buf, //发送的数据
.tx_len = strlen(hel), //长度
.transfer_mode = UART_SEND, //模式
};
plic_interrupt_t irq = (plic_interrupt_t){
.callback = uart_send_done, //回调函数
.ctx = NULL,
.priority = 1, //优先级
};
uart_handle_data_dma(UART_NUM, data, &irq); //串口dma 发送初始化
uart_data_t v_rx_data = (uart_data_t) //接受dma结构体
{
.rx_channel = DMAC_CHANNEL1, //通道
.rx_buf = recv_buf, //收到数据
.rx_len = RECV_DMA_LENTH, //接受长度
.transfer_mode = UART_RECEIVE, //模式
};
plic_interrupt_t v_rx_irq = (plic_interrupt_t){
.callback = uart_recv_done, //接受数据回调函数
.ctx = recv_buf,
.priority = 2,
};
uart_handle_data_dma(UART_NUM, v_rx_data,
&v_rx_irq); //串口dma 接收中断初始化
while (1) {
sleep(1);
uart_handle_data_dma(UART_NUM, data, &irq); //不停的发送hello
g_uart_send_flag = 1;
}
}