Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
modbus主机
touchgfx
信号量_semaphore
30
freemodbus主机+touchgfx+自行计算线程冲突挂起
发布于 2022-04-06 21:35:57 浏览:780
订阅该版
1. 硬件配置:ART-PI、正点原子7寸LCD 2. 软件环境:Rt-thread 4.02 3. 软件功能: - 利用touchgfx按键控件获取DCD9按键的ON和OFF两种状态; - 利用freemodbus主机获取DCD9传感器数据 - 自行编写“calculation”线程,进行屏幕按键状态传输与传感器数据打印计算功能。 **问题现象** - 如下图所示,无法进入按下DCD_9_OFF的状态 ![捕获.PNG](https://oss-club.rt-thread.org/uploads/20220406/948db90fab87059a3a697b6b5fa79375.png) if (DCD_9_click_flag == 1) if (DCD_9_STATE == 0) { //无法进入 } **其他发现:**针对 rt_sem_take(&sem_lock, RT_WAITING_FOREVER);等信号量操作中RT_WAITING_FOREVER进行修改为特定数据后,可进行DCD_9_OFF按键响应,但在DCD_9_ON状态中获取revbuf值存在大量0值。 程序段如下 ``` /* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2022-01-20 zf_19 the first version * 2022-03-12 zf_19 添加消息队列 */ #include
#include
#include "mb.h" #include "mb_m.h" #include "user_mb_app.h" #include
#include
#ifdef PKG_MODBUS_MASTER_SAMPLE #define SLAVE_ADDR MB_SAMPLE_TEST_SLAVE_ADDR #define PORT_NUM MB_MASTER_USING_PORT_NUM #define PORT_BAUDRATE MB_MASTER_USING_PORT_BAUDRATE #else #define SLAVE_ADDR 0x01 #define PORT_NUM 5 #define PORT_BAUDRATE 9600 #endif #define PORT_PARITY MB_PAR_NONE //无校验位 #define MB_POLL_THREAD_PRIORITY 10 #define MB_SEND_THREAD_PRIORITY RT_THREAD_PRIORITY_MAX - 1 #define MB_SEND_REG_START 3 #define MB_SEND_REG_NUM 3 #define MB_POLL_CYCLE_MS 10 //轮询间隔时间 2个传感器一轮走完需要40ms /*RS485_RE PI4 对应PI4引脚应填写:132 (I-A=8)*16+4=132 串口使用U5*/ /*各传感器地址配置*/ #define Displacement_sensor01_SLAVE_ADDR 0x05 //角度传感器地址 #define Raster_ruler_SLAVE_ADDR 0X0B //位移传感器(光栅尺)地址 /*寄存器地址配置*/ #define MB_READ_REG_00 0x00 //读当前测量值 #define MB_READ_REG_01 0x01 //仪表类比及当前信息 #define MB_READ_REG_02 0x02 //仪表编号低四位 #define MB_WRITE_REG_SET_0 0X0A /*寄存器数量---modbus 读数据的长度*/ #define MB_READ_REG_NUM_01 1 #define MB_READ_REG_NUM_02 2 #define MB_READ_REG_NUM_03 3 #define MB_READ_REG_NUM_04 4 #define MB_WRITE_REG_NUM_02 2 /*屏幕按键接收标志,此处不能赋初值,影响touchgfx-modle*/ int16_t is_got; extern USHORT usMRegHoldBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_HOLDING_NREGS]; // modbus master 用全局二维数组来记录多个从机的数据 /*初始化信号量*/ struct rt_semaphore sem_lock; struct rt_semaphore sem_empty, sem_full; /*指向modbus写入数据及计算线程获取数据位置*/ static rt_uint32_t set,get; /*定义最大缓冲数*/ #define MAXSEM 600 /*数据接收缓冲*/ rt_uint32_t Rev_buf[2][MAXSEM]; /*进行touchgfx数据更新、光栅尺、电压测量板显示数据格式为signed short -32768~32767*/ uint16_t value_DCD_9_H; //角度32位 uint16_t value_DCD_9_L; // int16_t value_DCD_9; uint16_t value_DCD_10_H; //位移32位 uint16_t value_DCD_10_L; uint32_t value_DCD_10; rt_uint32_t DCD_9_itinerry_data; rt_uint32_t DCD_9_speed_value; //返回DCD-10位移 static int getgfx_DCD_10_H(void) { return value_DCD_10_H; } static int getgfx_DCD_10_L(void) { return value_DCD_10_L; } static int getgfx_DCD_10(void) { return value_DCD_10; } //返回DCD-9角度 static int getgfx_DCD_9(void) { return value_DCD_9; } //返回DCD-9行程值 static int getgfx_DCD_9_itinerry_data(void) { return DCD_9_itinerry_data; } //返回DCD-9速度值 static int getgfx_DCD_9_speed_value(void) { return DCD_9_speed_value; } static uint8_t DCD_10_STATE = 0; static uint8_t DCD_9_STATE = 0; //使用click——flag 需要及时清零 static uint8_t DCD_10_click_flag = 0; static uint8_t DCD_9_click_flag = 0; /*touchgfx model层返回调用状态*/ static uint8_t DCD_10_state_ON() { DCD_10_STATE = 1; return 0; } static uint8_t DCD_10_state_OFF() { DCD_10_STATE = 0; return 0; } static uint8_t DCD_10_click() { DCD_10_click_flag = 1 ; return 0; } static uint8_t DCD_9_click() { DCD_9_click_flag = 1; return 0; } static uint8_t DCD_9_state_ON() { DCD_9_STATE = 1; return 0; } static uint8_t DCD_9_state_OFF() { DCD_9_STATE = 0; return 0; } /* 邮箱控制块 */ static struct rt_mailbox mb; /* 用于放邮件的内存池 */ static char mb_pool[128]; static char mb_str3[] = "over"; /*读取各传感器信息线程*/ static void send_thread_entry(void *parameter) { eMBMasterReqErrCode error_code = MB_MRE_NO_ERR; rt_uint16_t error_count = 0; rt_uint32_t count = 0; while (1) { //读角度传感器,0000H两个保持寄存器数据 error_code = eMBMasterReqReadHoldingRegister(Displacement_sensor01_SLAVE_ADDR, MB_READ_REG_00, MB_READ_REG_NUM_02, 500); //读位移传感器(光栅尺),0000H两个保持寄存器数据 error_code = eMBMasterReqReadHoldingRegister(Raster_ruler_SLAVE_ADDR, MB_READ_REG_00, //0000H寄存器 MB_READ_REG_NUM_02, //读取数据数量 500); rt_thread_mdelay(50); if (error_code == MB_MRE_NO_ERR) { //打印节点1角度传感器 保持寄存器的数据 value_DCD_9_H = (uint16_t) usMRegHoldBuf[Displacement_sensor01_SLAVE_ADDR - 1][0]; value_DCD_9_L = (uint16_t) usMRegHoldBuf[Displacement_sensor01_SLAVE_ADDR - 1][1]; //rt_kprintf("sensor1_detect: %x--%x \t\r\n", value_DCD_9_H,value_DCD_9_L); value_DCD_9 = ((value_DCD_9_H * 256) + (value_DCD_9_L / 256)); //rt_kprintf("sensor1_detect: %x %x %d \t\r\n", value_DCD_9_H,value_DCD_9_L,value_DCD_9); //打印节点A光栅尺 保持寄存器的数据 value_DCD_10_H = usMRegHoldBuf[Raster_ruler_SLAVE_ADDR - 1][0]; value_DCD_10_L = usMRegHoldBuf[Raster_ruler_SLAVE_ADDR - 1][1]; value_DCD_10 = (value_DCD_10_H * 256 * 256) + value_DCD_10_L; // rt_kprintf("sensor2_detect: %x %x %d \t\r\n", value_DCD_10_H, value_DCD_10_L, value_DCD_10); //打印时钟节点 //rt_kprintf("tick is %d\r\n",rt_tick_get()); if ((count < 600) && (DCD_9_STATE == 1)) { //生产者入口 /*获取一个空位*/ rt_sem_take(&sem_empty, RT_WAITING_FOREVER); /*修改REV_BUF内容上锁*/ rt_sem_take(&sem_lock,RT_WAITING_FOREVER); //rt_mb_send(&mb, (rt_ubase_t) &value_DCD_9); Rev_buf[0][set%MAXSEM] = value_DCD_9; Rev_buf[1][set%MAXSEM] = value_DCD_10; set++; rt_sem_release(&sem_lock); /*发布一个满位*/ rt_sem_release(&sem_full); count++; // rt_kprintf("get count is %d...\r\n",count); //rt_kprintf("Rev_buf is %d...\r\n",Rev_buf[0][count]); //rt_kprintf("data is %d...\r\n",value_DCD_9); } if (count == 600) { //发送邮件告诉线程1,已经运行发送 //rt_mb_send(&mb, (rt_uint32_t) &mb_str3); count = 0; set = 0; } else { } } else { error_count++; rt_kprintf("error_count : %d \n", error_count); rt_kprintf("error_code %d\r\n", error_code); } } } static void mb_master_poll(void *parameter) { //MB初始化 内部已定义停止位,当前为停止位2; eMBMasterInit(MB_RTU, PORT_NUM, PORT_BAUDRATE, PORT_PARITY); eMBMasterEnable(); while (1) { eMBMasterPoll(); rt_thread_mdelay(MB_POLL_CYCLE_MS); } } ALIGN(RT_ALIGN_SIZE) static char thread1_stack[4096]; static struct rt_thread thread1; static void calculation_entry(void *parameter) { char *str; rt_uint32_t count_CA = 0; rt_uint32_t now_data, last_data, last_last_data = 0; rt_uint32_t first_data = 0; rt_uint32_t set_falg = 0; uint8_t Now_state = 0; static uint8_t Last_state = 0; rt_uint32_t sum = 0; time_t start_t, end_t; double diff_t; uint32_t int_diff_t; clock_t t_now; Last_state = 0; while (1) { Now_state = DCD_9_STATE; //rt_kprintf("the DCD_9_SATTE IS %d\r\n", Now_state); //rt_kprintf(" DCD_9_click_flag is %d\n", DCD_9_click_flag); if (DCD_9_click_flag == 1) { DCD_9_click_flag = 0 ; rt_kprintf("STEP0 DCD_9_STATE is ______ %d\n", DCD_9_STATE); if (DCD_9_STATE == 0) { //DCD_9_click_flag = 0; //获取当前停止状态--计时差 //time(&end_t); //单位秒 end_t = clock(); diff_t = difftime(end_t, start_t); //解决rt_kprintf 不能打印浮点数 int_diff_t = diff_t; rt_kprintf("Execution time = %d.%d\n", int_diff_t / 1000, int_diff_t % 1000); //判断数据域中极值差即“行程” DCD_9_itinerry_data = last_data - first_data; rt_kprintf("xingcheng is %d\n", DCD_9_itinerry_data); //计算平均值即“线速度” } else if (DCD_9_STATE == 1) { //正在获取数据,获取开始计时 start_t = clock(); rt_kprintf("set 0n...\r\n"); } else { rt_kprintf("STEP3 is ______ %d\n", DCD_9_STATE); } } else { rt_kprintf("STEP4 DCD_9_STATE is %d,DCD_9_click_flag is %d\n", DCD_9_STATE,DCD_9_click_flag); if (DCD_9_STATE == 1) { // rt_kprintf("seting....\r\n"); /*获取一个满位*/ rt_sem_take(&sem_full, RT_WAITING_FOREVER); /*临界区,上锁进行操作*/ rt_sem_take(&sem_lock, RT_WAITING_FOREVER); sum += Rev_buf[0][get % MAXSEM]; //rt_kprintf("111\r\n"); rt_kprintf("the revbuf[%d] get a number: %d,time is %d\r\n", (get % MAXSEM), Rev_buf[0][get % MAXSEM],clock()); get++; rt_sem_release(&sem_lock); /*释放一个空位*/ rt_sem_release(&sem_empty); /*每获取10个数计算速度值*/ if ((get % 10) == 0) { if (get == 600) { get = 0; } DCD_9_speed_value = sum / 10; sum = 0; //get = 0; } } else if (DCD_9_STATE == 0) { rt_kprintf("STEP5 is ______ %d\n", DCD_9_STATE); } else { rt_kprintf("STEP6 is ______ %d\n", DCD_9_STATE); } } rt_thread_mdelay(20); } } static int TDM_TMD_modbus() { static rt_uint8_t is_init = 0; rt_thread_t tid1 = RT_NULL, tid2 = RT_NULL; rt_err_t result; if (is_init > 0) { rt_kprintf("sample is running\n"); return -RT_ERROR; } /* 初始化一个mailbox */ result = rt_mb_init(&mb, "mbt", /* 名称是mbt */ &mb_pool[0], /* 邮箱用到的内存池是mb_pool */ sizeof(mb_pool) / 4, /* 邮箱中的邮件数目,因为一封邮件占4字节 */ RT_IPC_FLAG_FIFO); /* 采用FIFO方式进行线程等待 */ if (result != RT_EOK) { rt_kprintf("init mailbox failed.\n"); return -1; } /*初始化信号量*/ rt_sem_init(&sem_lock, "lock", 1, RT_IPC_FLAG_PRIO); rt_sem_init(&sem_empty, "empty", MAXSEM, RT_IPC_FLAG_PRIO); rt_sem_init(&sem_full, "full", 0, RT_IPC_FLAG_PRIO); /*创建线程*/ tid1 = rt_thread_create("md_m_poll", mb_master_poll, RT_NULL, 512, MB_POLL_THREAD_PRIORITY, 10); if (tid1 != RT_NULL) { rt_thread_startup(tid1); } else { goto __exit; } tid2 = rt_thread_create("md_m_send", send_thread_entry, RT_NULL, 4096, MB_SEND_THREAD_PRIORITY, 10); if (tid2 != RT_NULL) { rt_thread_startup(tid2); } else { goto __exit; } rt_thread_init(&thread1, "calculation", calculation_entry, RT_NULL, &thread1_stack[0], sizeof(thread1_stack), 9, 5); rt_thread_startup(&thread1); return RT_EOK; //退出 __exit: if (tid1) rt_thread_delete(tid1); if (tid2) rt_thread_delete(tid2); return -RT_ERROR; } //导出命令行 MSH_CMD_EXPORT(TDM_TMD_modbus, run a TDM_DTECT sample); //开机启动 //INIT_APP_EXPORT(Z_TDM_TMD_modbus); ```
查看更多
2
个回答
默认排序
按发布时间排序
出出啊
2022-04-07
恃人不如自恃,人之为己者不如己之自为也
4.0.2? 升级吧,换 4.1.0 。 你那个版本有很多已知致命 bug。可能包括你现在遇到的这个
daoHeng
2022-04-07
这家伙很懒,什么也没写!
😥
撰写答案
登录
注册新账号
关注者
0
被浏览
780
关于作者
daoHeng
这家伙很懒,什么也没写!
提问
3
回答
2
被采纳
0
关注TA
发私信
相关问题
1
RT-STUDIO下加入TOUCHGFX?
2
ART-Pi 在 Studio 中使用TouchGFX Library 编译报错
3
APT-Pi运行Touchgfx例程出现错误
4
请问程序烧到内部rom后,如何把touchgfx图片数据烧到片外8M闪存里
5
ART-PI 在运行Touchgfx时如果打开wifi就在初始化时有一段时间乱码
6
ART-Pi在同时打开板载wifi例程和touchgfx后发生乱屏的现象
7
ART-PI的Touchgfx按键事件没反应
8
TouchGFX从文件系统中读取图片失败
9
TouchGFX如何从文件系统中读取字库
10
将ExtFlashSection映射到添加的USB区域后,程序下载失败
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
2
RT-Thread 发布 EtherKit开源以太网硬件!
3
rt-thread使用cherryusb实现虚拟串口
4
《C++20 图形界面程序:速度与渲染效率的双重优化秘籍》
5
《原子操作:程序世界里的“最小魔法单位”解析》
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
ota在线升级
UART
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
at_device
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
张世争
8
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
KunYi
6
个答案
1
次被采纳
本月文章贡献
程序员阿伟
6
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部