NRF52832开发:普通串口驱动
NRF52832开发:普通串口驱动本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 环境:开发环境:MDK5.23说明:编写NRF52832普通串口的驱动,发送是查询方式,接收采用中断方式。接收时每20ms处理一次。源代码:drv_uart.h/*** Copyrig
·
NRF52832开发:普通串口驱动
本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.
环境:
开发环境:MDK5.23
说明:
编写NRF52832普通串口的驱动,发送是查询方式,接收采用中断方式。接收时每20ms处理一次。
源代码:
drv_uart.h
/**
* Copyright (c), 2015-2025
* @file drv_uart.h
* @brief 串口驱动层头文件
* @author jdh
* @email jdh821@163.com
* @date 2017/7/4
* @verbatim
* 硬件连接说明
* 电路标号 单片机引脚
* USART1_TX P0.08
* USART1_RX P0.06
* @endverbatim
*/
#ifndef _DRV_UART_H_
#define _DRV_UART_H_
/*********************************************************************
* 头文件
**********************************************************************/
#include "stdint.h"
/*********************************************************************
* 宏定义
**********************************************************************/
/**
* @brief 波特率值
*/
#define BAUD1200 0x0004F000
#define BAUD2400 0x0009D000
#define BAUD4800 0x0013B000
#define BAUD9600 0x00275000
#define BAUD14400 0x003B000
#define BAUD19200 0x004EA000
#define BAUD28800 0x0075F000
#define BAUD38400 0x009D5000
#define BAUD57600 0x00EBF000
#define BAUD76800 0x013A9000
#define BAUD115200 0x01D7E000
#define BAUD230400 0x03AFB000
#define BAUD250000 0x04000000
#define BAUD460800 0x075F7000
#define BAUD921600 0x0EBED000
#define BAUD1M 0x10000000
/**
* @brief 默认的波特率
*/
#define DEFAULT_BAUD BAUD1M
/**
* @brief IO口
*/
#define PIN_UART_TX 6
#define PIN_UART_RX 8
/*********************************************************************
* 函数
**********************************************************************/
/**
* @brief 初始模块
*/
void drv_uart_init(void);
/**
* @brief 串口发送数据
* @param data:发送数据存放地址
* @param size:发送数据字节数
*/
void drv_uart_tx(uint8_t *data, uint16_t size);
/**
* @brief 处理接收完成中断
* @retval 接收到的字节
*/
uint8_t drv_uart_deal_irq_rx_end(void);
#endif
drv_uart.c
/**
* Copyright (c), 2015-2025
* @file drv_uart.c
* @brief 串口驱动层主文件
* @author jdh
* @email jdh821@163.com
* @date 2017/7/4
*/
/*********************************************************************
* 头文件
**********************************************************************/
#include "drv_uart.h"
#include "drv_gpio.h"
#include "nrf.h"
#include "drv_irq_priority.h"
/*********************************************************************
* 静态函数
**********************************************************************/
static void init_io(void);
static void init_uart(void);
static void enable_interrupt(void);
/*********************************************************************
* 函数
**********************************************************************/
/**
* @brief 初始模块
*/
void drv_uart_init(void)
{
init_io();
init_uart();
}
static void init_io(void)
{
drv_gpio_config_output(PIN_UART_TX);
drv_gpio_set_high(PIN_UART_TX);
drv_gpio_config_input(PIN_UART_RX, GPIO_NOPULL);
}
static void init_uart(void)
{
NRF_UART0->BAUDRATE = DEFAULT_BAUD;
NRF_UART0->PSELTXD = PIN_UART_TX;
NRF_UART0->PSELRXD = PIN_UART_RX;
enable_interrupt();
// 使能串口
NRF_UART0->ENABLE = UART_ENABLE_ENABLE_Enabled;
NRF_UART0->TASKS_STARTTX = 1;
NRF_UART0->TASKS_STARTRX = 1;
}
static void enable_interrupt(void)
{
NRF_UART0->EVENTS_RXDRDY = 0;
NRF_UART0->INTENSET = UART_INTENSET_RXDRDY_Enabled << UART_INTENSET_RXDRDY_Pos;
NVIC_SetPriority(UART0_IRQn, IRQ_PRIORITY_LOW);
NVIC_ClearPendingIRQ(UART0_IRQn);
NVIC_EnableIRQ(UART0_IRQn);
}
/**
* @brief 串口发送数据
* @param data:发送数据存放地址
* @param size:发送数据字节数
*/
void drv_uart_tx(uint8_t *data, uint16_t size)
{
for (int i = 0; i < size; i++)
{
NRF_UART0->TXD = data[i];
while (NRF_UART0->EVENTS_TXDRDY == 0);
NRF_UART0->EVENTS_TXDRDY = 0;
}
}
/**
* @brief 处理接收完成中断
* @retval 接收到的字节
*/
uint8_t drv_uart_deal_irq_rx_end(void)
{
NRF_UART0->EVENTS_RXDRDY = 0;
return NRF_UART0->RXD;
}
console.h
/**
* Copyright (c), 2015-2025
* @file deal_console.h
* @brief 控制台接收数据处理模块头文件
* @author jdh
* @date 2016/7/28
* @update 2016/8/8
* @update 2017/10/20
*/
#ifndef _DEAL_CONSOLE_H_
#define _DEAL_CONSOLE_H_
/*********************************************************************
* 头文件
**********************************************************************/
#include "world.h"
#include "console.h"
/*********************************************************************
* 函数
**********************************************************************/
/**
* @brief 接收处理
* @param rx:接收数据
*/
void deal_console_rx(T_Buffer rx);
#endif
console.c
/**
* Copyright (c), 2015-2025
* @file console.c
* @brief 控制台主文件
* @author jdh
* @date 2015/3/16
* @update 2015/6/30
* @update 2015/8/12
* @update 2016/10/25
* @update 2017/10/20
*/
/*********************************************************************
* 头文件
**********************************************************************/
#include "console.h"
/*********************************************************************
* 宏定义
**********************************************************************/
/**
* @brief 观察者最大个数
*/
#define MAX_OBSERVER 10
/*********************************************************************
* 静态变量
**********************************************************************/
/**
* @brief pt任务变量
*/
static struct pt Pt_Task;
/**
* @brief 接收数据观察者列表
*/
static T_Console_Rx Observer[MAX_OBSERVER];
static uint8_t Len_Observer = 0;
/**
* @brief 接收数据
*/
static T_Buffer Buffer_Rx;
static bool Is_Rx = false;
/*********************************************************************
* 静态函数
**********************************************************************/
static int pt_run(struct pt *pt);
static void notify_observer(void);
/*********************************************************************
* 函数
**********************************************************************/
/**
* @brief 模块载入
*/
void console_load(void)
{
PT_INIT(&Pt_Task);
}
/**
* @brief 模块运行
*/
void console_run(void)
{
pt_run(&Pt_Task);
}
static int pt_run(struct pt *pt)
{
static T_Time time_delay;
PT_BEGIN(pt);
time_delay = get_time();
PT_WAIT_UNTIL(pt,sub_time_safe(get_time(),&time_delay) > INTERVAL_CONSOLE * 1000);
if (Is_Rx)
{
Is_Rx = false;
}
else
{
if (Buffer_Rx.len > 0)
{
notify_observer();
Buffer_Rx.len = 0;
}
}
PT_END(pt);
}
static void notify_observer(void)
{
for (int i = 0;i < Len_Observer;i++)
{
Observer[i](Buffer_Rx);
}
}
/**
* @brief 注册观察者
* @param function:观察者函数指针
*/
void console_register_observer(T_Console_Rx function)
{
Observer[Len_Observer++] = function;
}
/**
* @brief 串口中断处理函数
* @param data:接收数据存放地址
*/
void console_irq_handler(void)
{
Buffer_Rx.buf[Buffer_Rx.len++] = drv_uart_deal_irq_rx_end();
Is_Rx = true;
}
/**
* @brief 向控制台发送数据
* @param data:发送数据存放地址
* @param size:发送数据字节数
*/
void console_tx(uint8_t *data,uint16_t size)
{
drv_uart_tx(data, size);
}
中断处理函数:
void UARTE0_UART0_IRQHandler(void)
{
console_irq_handler();
}
测试用例:
deal_console.h:
/**
* Copyright (c), 2015-2025
* @file deal_console.h
* @brief 控制台接收数据处理模块头文件
* @author jdh
* @date 2016/7/28
* @update 2016/8/8
* @update 2017/10/20
*/
#ifndef _DEAL_CONSOLE_H_
#define _DEAL_CONSOLE_H_
/*********************************************************************
* 头文件
**********************************************************************/
#include "world.h"
#include "console.h"
/*********************************************************************
* 函数
**********************************************************************/
/**
* @brief 接收处理
* @param rx:接收数据
*/
void deal_console_rx(T_Buffer rx);
#endif
deal_console.c:
/**
* Copyright (c), 2015-2025
* @file deal_console.c
* @brief 控制台接收数据处理模块主文件
* @date 2016/7/28
* @upate 2016/7/29
* @upate 2016/8/1
* @upate 2016/8/8
* @upate 2016/8/10
* @upate 2016/8/11
* @upate 2016/8/17
* @upate 2016/8/18
* @update 2016/9/2
* @update 2016/9/5
* @update 2016/9/12
* @update 2016/9/13
* @update 2016/9/21
* @update 2016/9/23
* @update 2016/10/19
* @update 2017/10/20
* @update 2017/10/23
*/
/*********************************************************************
* 头文件
**********************************************************************/
#include "deal_console.h"
#include "radio_rx.h"
/*********************************************************************
* 静态函数
**********************************************************************/
/**
* @brief 搜索字符串出现下标
* @param src:源字符串
* @param dst:目标字符串
* @param begin:开始下标
* @param num:第几次出现,从1开始
* @retval -1:失败,其他:下标
*/
static int search_string(char *src,char *dst,int begin,int num);
/**
* @brief 复位基站
* @param offset:正文偏移
* @param rx:接收数据
*/
static void deal_cmd_bus_reset(uint16_t offset, T_Buffer rx);
/**
* @brief 设置接收频点
* @param offset:正文偏移
* @param rx:接收数据
*/
static void deal_cmd_bus_set_rx_freq(uint16_t offset, T_Buffer rx);
/**
* @brief 读取接收频点
* @param offset:正文偏移
* @param rx:接收数据
*/
static void deal_cmd_bus_get_rx_freq(uint16_t offset, T_Buffer rx);
static void help(void);
/*********************************************************************
* 函数
**********************************************************************/
/**
* @brief 接收处理
* @param rx:接收数据
*/
void deal_console_rx(T_Buffer rx)
{
uint16_t offset = 0;
uint8_t cmd = 0;
int result = 0;
//读取命令字
//复位
result = search_string((char *)rx.buf, "RESET", 0, 1);
if (result != -1)
{
//处理
deal_cmd_bus_reset(result, rx);
return;
}
//设置接收频点
result = search_string((char *)rx.buf, "SET_FREQ", 0, 1);
if (result != -1)
{
//处理
deal_cmd_bus_set_rx_freq(result, rx);
return;
}
//读取接收频点
result = search_string((char *)rx.buf, "READ_FREQ", 0, 1);
if (result != -1)
{
//处理
deal_cmd_bus_get_rx_freq(result, rx);
return;
}
if (rx.len == 1 && rx.buf[0] == 'H')
{
help();
}
}
/**
* @brief 搜索字符串出现下标
* @param src:源字符串
* @param dst:目标字符串
* @param begin:开始下标
* @param num:第几次出现,从1开始
* @retval -1:失败,其他:下标
*/
static int search_string(char *src,char *dst,int begin,int num)
{
int i = 0;
int j = 0;
int len1 = 0;
int len2 = 0;
int count = 0;
if (num == 0)
{
return -1;
}
len1 = strlen(src);
len2 = strlen(dst);
if (len1 < len2)
{
return -1;
}
for (i = begin;i <= len1 - len2;i++)
{
for (j = 0;j < len2;j++)
{
if (src[i + j] != dst[j])
{
break;
}
}
if (j >= len2)
{
count++;
if (count == num)
{
return i;
}
}
}
return -1;
}
/**
* @brief 复位基站
* @param offset:正文偏移
* @param rx:接收数据
*/
static void deal_cmd_bus_reset(uint16_t offset, T_Buffer rx)
{
//回复
console_tx((uint8_t *)"CONFIRM+RESET\r\n", strlen("CONFIRM+RESET\r\n"));
//复位
NVIC_SystemReset();
}
/**
* @brief 设置接收频点
* @param offset:正文偏移
* @param rx:接收数据
*/
static void deal_cmd_bus_set_rx_freq(uint16_t offset, T_Buffer rx)
{
int freq, len;
sscanf((char *)rx.buf, "SET_FREQ+%d+%d", &freq, &len);
// 判断频率是否正确
if (freq < 2360 || freq > 2500)
{
return;
}
// 判断长度是否正确
if (len > 100)
{
return;
}
//设置接收频点
//radio_rx_start(freq, len);
radio_rx_stop();
radio_rx_start(freq, len);
// drv_radio_set_frequency(freq);
// drv_radio_set_playload_length(len);
//回复
console_tx((uint8_t *)"CONFIRM+SET_FREQ\r\n", strlen("CONFIRM+SET_FREQ\r\n"));
}
/**
* @brief 读取接收频点
* @param offset:正文偏移
* @param rx:接收数据
*/
static void deal_cmd_bus_get_rx_freq(uint16_t offset, T_Buffer rx)
{
int freq, len;
char arr[128] = {0};
//模块接收频点
freq = drv_radio_get_frequency();
len = drv_radio_get_playload_length();
//回复
sprintf(arr, "SEND_FREQ+%d+%d\r\n", freq, len);
console_tx((uint8_t *)arr, strlen(arr));
}
static void help(void)
{
char log_out[100] = {0};
strcpy(log_out,"*******************************************\r\n");
console_tx((uint8_t *)log_out,strlen(log_out));
strcpy(log_out," Sniffer帮助界面 \r\n");
console_tx((uint8_t *)log_out,strlen(log_out));
sprintf(log_out,"硬件版本:%d 软件版本:%d\r\n", VERSION_HARD, VERSION_SOFT);
console_tx((uint8_t *)log_out,strlen(log_out));
sprintf(log_out,"H:帮助\r\n");
console_tx((uint8_t *)log_out,strlen(log_out));
sprintf(log_out,"RESET:复位\r\n");
console_tx((uint8_t *)log_out,strlen(log_out));
sprintf(log_out,"SET_FREQ:设置频点.例:SET_FREQ+2400\r\n");
console_tx((uint8_t *)log_out,strlen(log_out));
sprintf(log_out,"READ_FREQ:读取频点\r\n");
console_tx((uint8_t *)log_out,strlen(log_out));
strcpy(log_out,"*******************************************\r\n");
console_tx((uint8_t *)log_out,strlen(log_out));
}
在main.c中注册及调用:
int main(void)
{
world_load();
spi_load();
reg_management_load();
test_load();
console_load();
drv_radio_config(RADIO_TXPOWER_POS4DBM, 2400, RADIO_BAUDRATE_1M, 0x11223344, 14);
// // test
// radio_tx_stop();
// radio_rx_stop();
//
// RADIO_SR.FREQ = 40;
// RADIO_SR.LENGTH = 14;
// RADIO_SR.STATE = BITS_RADIO_STATE_RX;
// radio_rx_start(RADIO_SR.FREQ + BITS_BASE_FREQ, RADIO_SR.LENGTH);
// 观察者注册
spi_register_observer(reg_management_deal_spi_rx);
radio_tx_register_observer(reg_management_deal_radio_tx_events);
radio_rx_register_observer(reg_management_deal_radio_rx_events);
console_register_observer(deal_console_rx);
radio_rx_start(2400, 14);
uint8_t arr[28] = {0};
while (1)
{
radio_rx_run();
console_run();
}
}
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献2条内容
所有评论(0)