陈斌
陈斌

注册于 1 year ago

回答
7
文章
0
关注者
0

可以使用 ctime_r讲日期输出到内存中

char *ctime_r(const time_t *, char *);

这个有点麻烦,如果有网络的话可以用tftp 来传。
如果没有网络看有没有usb,用usb虚拟u盘来传

掉线的状态是emqx上看不到客户端了,但是这个网络连接好些还是保持的

最后调式稳定的代码,可以直接拿去用

使用了ringbuffer环形数组代码来自完整版的工程目录DeviceDrivers下,可直接拿过来用,
主要问题在于
1.中断的处理
主要是发送和接收的中断处理响应,中断程序一定要简单快速

2.在中断里面发送信号量产生线程调度
在用操作系统时切记进入中断后调用rt_interrupt_enter();
退出中断时调用rt_interrupt_leave();
这会告诉系统,你现在进入了中断环境,系统在切换线程时算法有所不同





#include "ringbuffer.h"

struct rt_semaphore shell_rx_sem;
struct rt_ringbuffer u1_rbuff;
uint8_t u1_buff[64]={0};

void rt_hw_console_output(const char *str)
{
rt_size_t i = 0, size = 0;
char a = '\r';

__HAL_UNLOCK(&huart1);

size = rt_strlen(str);
rt_enter_critical();
for (i = 0; i < size; i++)
{
if (*(str + i) == '\n')
{
HAL_UART_Transmit(&huart1, (uint8_t *)&a, 1, 1);
}
HAL_UART_Transmit(&huart1, (uint8_t *)(str + i), 1, 1);
}
rt_exit_critical();
}

char rt_hw_console_getchar(void)
{
int ch = -1;
while(rt_ringbuffer_getchar(&u1_rbuff,(uint8_t *)&ch) != 1)
rt_sem_take(&shell_rx_sem, RT_WAITING_FOREVER);

return ch;
}

int rt_hw_console_UART_Init(void)
{
rt_sem_init(&shell_rx_sem, "shell_rx", 0, 0);
rt_ringbuffer_init(&u1_rbuff,u1_buff,64);

huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* 中断配置 */

HAL_NVIC_EnableIRQ(USART1_IRQn);
HAL_NVIC_SetPriority(USART1_IRQn, 1, 0);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);
//__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);

__HAL_UART_CLEAR_IDLEFLAG(&huart1);
return 0;
}
INIT_BOARD_EXPORT(rt_hw_console_UART_Init);

void USART1_IRQHandler(void)
{
rt_interrupt_enter();
if ((__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&huart1, UART_IT_RXNE) != RESET))//接收中断
{
__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE);
rt_ringbuffer_putchar(&u1_rbuff,(uint8_t)(huart1.Instance->DR & 0xff));
rt_sem_release(&shell_rx_sem);//释放信号量
}else if ((__HAL_UART_GET_FLAG(&(huart1), UART_FLAG_IDLE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&(huart1), UART_IT_IDLE) != RESET))
{
__HAL_UART_CLEAR_IDLEFLAG(&(huart1));
//rt_sem_control(&shell_rx_sem, RT_IPC_CMD_RESET, RT_NULL);
}else
{
if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_ORE) != RESET)
{
__HAL_UART_CLEAR_OREFLAG(&huart1);
}
if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_NE) != RESET)
{
__HAL_UART_CLEAR_NEFLAG(&huart1);
}
if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_FE) != RESET)
{
__HAL_UART_CLEAR_FEFLAG(&huart1);
}
if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_PE) != RESET)
{
__HAL_UART_CLEAR_PEFLAG(&huart1);
}
}
rt_interrupt_leave();
}





问题出在串口发送没有临界值保护,fifo不收保护的,而且没有系统调度,加信号量控制的原因是因为实时性高,只要信号量一释放,接收信号量的线程就会运行

这是我目前的代码,调式时不会出错,串口SR ,DR寄存器都显示正常
但是一旦离开调试,会不确定的finsh无法输入,或者是放置一段时间就无法输入,只能重启


struct rt_semaphore shell_rx_sem;
struct rt_ringbuffer u1_rbuff;
uint8_t u1_buff[64]={0};

void rt_hw_console_output(const char *str)
{
rt_size_t i = 0, size = 0;
char a = '\r';

__HAL_UNLOCK(&huart1);

size = rt_strlen(str);
for (i = 0; i < size; i++)
{
if (*(str + i) == '\n')
{
HAL_UART_Transmit(&huart1, (uint8_t *)&a, 1, 1);
}
HAL_UART_Transmit(&huart1, (uint8_t *)(str + i), 1, 1);
}
}

char rt_hw_console_getchar(void)
{
int ch = -1;
// if(rt_ringbuffer_data_len(&u1_rbuff)>0)
// {
// rt_ringbuffer_getchar(&u1_rbuff,(uint8_t *)&ch);//读取数据
// }else
// {
// if(rt_sem_take(&shell_rx_sem, RT_WAITING_FOREVER) == RT_EOK) //接收信号量
// {
// rt_ringbuffer_getchar(&u1_rbuff,(uint8_t *)&ch);//读取数据
// }
// }

while(rt_ringbuffer_getchar(&u1_rbuff,(uint8_t *)&ch) != 1)
rt_sem_take(&shell_rx_sem, RT_WAITING_FOREVER);

return ch;
}

int rt_hw_console_UART_Init(void)
{
rt_sem_init(&shell_rx_sem, "shell_rx", 0, 0);
rt_ringbuffer_init(&u1_rbuff,u1_buff,64);

huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* 中断配置 */

HAL_NVIC_EnableIRQ(USART1_IRQn);
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);
__HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_TXE);
__HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_RXNE);
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
return 0;
}
INIT_BOARD_EXPORT(rt_hw_console_UART_Init);

void USART1_IRQHandler(void)
{
uint8_t c=0;
// if ((__HAL_UART_GET_FLAG(&huart1, UART_FLAG_ORE) != RESET) )
// {
// __HAL_UART_CLEAR_OREFLAG(&huart1);
// }
//
// if ((__HAL_UART_GET_FLAG(&huart1, UART_FLAG_FE) != RESET) )
// {
// __HAL_UART_CLEAR_FEFLAG(&huart1);
// }
// if ((__HAL_UART_GET_FLAG(&huart1, UART_FLAG_NE) != RESET) )
// {
// __HAL_UART_CLEAR_NEFLAG(&huart1);
// }

if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET)//接收中断
{
__HAL_UART_CLEAR_FLAG(&(huart1), UART_FLAG_RXNE); //清除中断
rt_ringbuffer_putchar(&u1_rbuff,(uint8_t)(huart1.Instance->DR & 0xff));
rt_sem_control(&shell_rx_sem, RT_IPC_CMD_RESET, RT_NULL);
rt_sem_release(&shell_rx_sem);//释放信号量
}


// if ((__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) != RESET) )
// {
// __HAL_UART_CLEAR_IDLEFLAG(&huart1);
// }
}





左耳朵的耗子 发表于 2019-12-12 16:37
如果要在nano使用shell,稳定跑一定更要在串口接收fifo,不然很容易卡住!!!, ...


还是有点问题,突发性的,在输入命令时如果遇到一个线程切换就一会突然没反应,然后就输入不了了



struct rt_semaphore shell_rx_sem;
struct rt_ringbuffer u1_rbuff;
uint8_t u1_buff[256]={0};

void rt_hw_console_output(const char *str)
{
rt_size_t i = 0, size = 0;
char a = '\r';

__HAL_UNLOCK(&huart1);

size = rt_strlen(str);
for (i = 0; i < size; i++)
{
if (*(str + i) == '\n')
{
HAL_UART_Transmit(&huart1, (uint8_t *)&a, 1, 1);
}
HAL_UART_Transmit(&huart1, (uint8_t *)(str + i), 1, 1);
}
}

char rt_hw_console_getchar(void)
{
int ch = -1;
if(rt_ringbuffer_data_len(&u1_rbuff)>0)
{
rt_ringbuffer_getchar(&u1_rbuff,(uint8_t *)&ch);//读取数据
}else
if(rt_sem_take(&shell_rx_sem, RT_WAITING_FOREVER)) //接收信号量
{
rt_ringbuffer_getchar(&u1_rbuff,(uint8_t *)&ch);//读取数据
}
return ch;
}

int rt_hw_console_UART_Init(void)
{
rt_sem_init(&shell_rx_sem, "shell_rx", 0, 0);
rt_ringbuffer_init(&u1_rbuff,u1_buff,256);

huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* 中断配置 */
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);
HAL_NVIC_EnableIRQ(USART1_IRQn);
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
return 0;
}
INIT_BOARD_EXPORT(rt_hw_console_UART_Init);

void USART1_IRQHandler(void)
{
//huart1.Instance->SR;
if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET)//接收中断
{
__HAL_UART_CLEAR_FLAG(&(huart1), UART_FLAG_RXNE); //清除中断
rt_ringbuffer_putchar(&u1_rbuff,(uint8_t)(huart1.Instance->DR & 0xff));
rt_sem_release(&shell_rx_sem); //释放信号量
}
}


左耳朵的耗子 发表于 2019-12-12 16:37
如果要在nano使用shell,稳定跑一定更要在串口接收fifo,不然很容易卡住!!!, ...


我已经改了,找到原因了

线程超时是什么原因引起的?

测试了,没问题,就是那个漏掉了
struct rt_semaphore shell_rx_sem;

还有SystemClock_Config没有被调用,感觉主频会跟cubemx的配置不太一样。

cubemx生成的代码里面如果能在app_rtthread.c里面加上
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */
的代码来区分用户代码,这样rtt nano和cubemx结合起来用会更方便

发布
问题

分享
好友