RT-Thread基于AT32单片机的485应用开发(三)Modbus从机

RT-Thread中已经有不少Modbus相关在线软件包,但总体应用起来还是相对复杂,所以在RT-Thread基于AT32单片机的485应用开发(二)的基础上实现了一个极简Modbus从机,支持Modbus功能码01,02,03,04,05,06,15,16。

在具体项目中只要实现下面几个函数就可以直接用了,不过需要注意多线程访问变量加锁问题。

rt_weak rt_err_t mb_write_coil_cb(unsigned short addr, unsigned short val){return RT_EOK;}
rt_weak rt_err_t mb_write_holding_cb(unsigned short addr, unsigned short val){return RT_EOK;}
rt_weak unsigned short mb_read_coil_cb(unsigned short addr){return 0;}
rt_weak unsigned short mb_read_di_cb(unsigned short addr){return 0;}
rt_weak unsigned short mb_read_holding_cb(unsigned short addr){return 0;}
rt_weak unsigned short mb_read_input_cb(unsigned short addr){return 0;}

只需要在项目中增加两个文件,就可以实现基于RS485的ModbusRTU设备。

1. mb_core.c

#include <rtthread.h>static unsigned int MB_COIL_NUM    = 16;
static unsigned int MB_DI_NUM      = 16;
static unsigned int MB_HOLDING_NUM = 32;
static unsigned int MB_INPUT_NUM   = 32;static unsigned char DEV_ADDR = 1;rt_weak rt_err_t mb_write_coil_cb(unsigned short addr, unsigned short val){return RT_EOK;}
rt_weak rt_err_t mb_write_holding_cb(unsigned short addr, unsigned short val){return RT_EOK;}
rt_weak unsigned short mb_read_coil_cb(unsigned short addr){return 0;}
rt_weak unsigned short mb_read_di_cb(unsigned short addr){return 0;}
rt_weak unsigned short mb_read_holding_cb(unsigned short addr){return 0;}
rt_weak unsigned short mb_read_input_cb(unsigned short addr){return 0;}/* 高位字节的 CRC 值 */
static unsigned char auchCRCHi[] = { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1,0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 };
/* 低位字节的 CRC 值 */
static char auchCRCLo[] = { 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8,0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5,0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33,0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E,0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3,0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5,0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8,0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4,0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F,0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A,0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82,0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40 };static unsigned short CRC16_ModBus(unsigned char *puchMsg, unsigned char usDataLen)
{unsigned char uchCRCHi = 0xFF; /* CRC 的高字节初始化 */unsigned char uchCRCLo = 0xFF; /* CRC 的低字节初始化 */unsigned char uIndex; /* CRC 查询表索引 */while (usDataLen--) /* 完成整个报文缓冲区 */{uIndex = uchCRCLo ^ *puchMsg++; /* 计算 CRC */uchCRCLo = uchCRCHi ^ auchCRCHi[uIndex];uchCRCHi = auchCRCLo[uIndex];}return (uchCRCHi << 8 | uchCRCLo);
}static int frame_available(unsigned char *buf, int len)
{int data_len = 0, num;if (len < 5)return 0;if (buf[1] == 1 || buf[1] == 2 || buf[1] == 3 || buf[1] == 4 || buf[1] == 5 || buf[1] == 6){data_len = 4;}else if (buf[1] == 15){num = ((buf[4] << 8) | buf[5]);data_len = 4 + 1 + (num + 7) / 8;}else if (buf[1] == 16){num = ((buf[4] << 8) | buf[5]);data_len = 4 + 1 + num * 2;}else if (buf[1] & 0x80){data_len = 1;}else{return -1;}if (len < data_len + 4)return 0;unsigned short crc = CRC16_ModBus(buf, 2 + data_len);if (crc == (buf[2 + data_len] | ((buf[2 + data_len + 1]) << 8))){return 1;}return -1;
}void mb_slave_init(unsigned char slave_addr, int coil_num, int di_num, int holding_num, int input_num)
{MB_COIL_NUM    = coil_num;MB_DI_NUM      = di_num;MB_HOLDING_NUM = holding_num;MB_INPUT_NUM   = input_num;DEV_ADDR = slave_addr;
}int mb_slave_process(unsigned char *rx_buf, int rx_len, unsigned char *tx_buf)
{unsigned char error_code = 0;unsigned short num, addr, val, ind = 0, crc16, bytes;int ret = frame_available(rx_buf, rx_len);//frame errorif (ret <= 0)return ret;//valid addrif (rx_buf[0] != DEV_ADDR)return 0;//process rtu cmdswitch (rx_buf[1]){case 1: //read coilcase 2: //read diaddr = (rx_buf[2] << 8) | rx_buf[3];num = (rx_buf[4] << 8) | rx_buf[5];if (num < 1 || num > 0x7d0){error_code = 3;break;}if (addr + num > (rx_buf[1] == 1 ? MB_COIL_NUM : MB_DI_NUM)){error_code = 2;break;}tx_buf[ind++] = DEV_ADDR;tx_buf[ind++] = rx_buf[1];bytes = (num + 7) / 8;tx_buf[ind++] = bytes;for (int i = 0; i < bytes; i++){tx_buf[ind + i] = 0;}for (int i = 0; i < num; i++){if (rx_buf[1] == 1)//coil{val = mb_read_coil_cb(i + addr);if (val)tx_buf[ind + i / 8] |= 1 << (i % 8);}else//di{val = mb_read_di_cb(i + addr);if (val)tx_buf[ind + i / 8] |= 1 << (i % 8);}}ind += bytes;crc16 = CRC16_ModBus(tx_buf, ind);tx_buf[ind++] = crc16;tx_buf[ind++] = crc16 >> 8;break;case 3: //read holdingcase 4: //read inputaddr = (rx_buf[2] << 8) | rx_buf[3];num = (rx_buf[4] << 8) | rx_buf[5];if (num < 1 || num > 125){error_code = 3;break;}if (addr + num > (rx_buf[1] == 3 ? MB_HOLDING_NUM : MB_INPUT_NUM)){error_code = 2;break;}tx_buf[ind++] = DEV_ADDR;tx_buf[ind++] = rx_buf[1];tx_buf[ind++] = num * 2;for (int i = 0; i < num; i++){if (rx_buf[1] == 3)//holding{val = mb_read_holding_cb(i + addr);tx_buf[ind++] = val >> 8;tx_buf[ind++] = val;}else//input{val = mb_read_input_cb(i + addr);tx_buf[ind++] = val >> 8;tx_buf[ind++] = val;}}crc16 = CRC16_ModBus(tx_buf, ind);tx_buf[ind++] = crc16;tx_buf[ind++] = crc16 >> 8;break;case 5: //write single coilcase 6: //write single regaddr = (rx_buf[2] << 8) | rx_buf[3];val = (rx_buf[4] << 8) | rx_buf[5];if (val != 0x0 && val != 0xff00 && rx_buf[1] == 5){error_code = 3;break;}if (addr> (rx_buf[1] == 5 ? MB_COIL_NUM : MB_HOLDING_NUM)){error_code = 2;break;}for (int i = 0; i < 8; i++){tx_buf[i] = rx_buf[i];}if (rx_buf[1] == 5){if (0 != mb_write_coil_cb(addr, val))error_code = 4;}else{if (0 != mb_write_holding_cb(addr, val))error_code = 4;}ind = 8;break;case 15: //wrtie multi coilsaddr = (rx_buf[2] << 8) | rx_buf[3];num = (rx_buf[4] << 8) | rx_buf[5];if (num < 1 || num > 0x7b || rx_buf[6] != (num + 7) / 8){error_code = 3;break;}if (addr + num > MB_COIL_NUM){error_code = 2;break;}for (ind = 0; ind < 6; ind++){tx_buf[ind] = rx_buf[ind];}for (int i = 0; i < num; i++){val = rx_buf[7 + i / 8] & (1 << (i % 8));if (mb_write_coil_cb(addr + i, val) != 0)error_code = 4;}crc16 = CRC16_ModBus(tx_buf, ind);tx_buf[ind++] = crc16;tx_buf[ind++] = crc16 >> 8;break;case 16: //write multi regsaddr = (rx_buf[2] << 8) | rx_buf[3];num = (rx_buf[4] << 8) | rx_buf[5];if (num < 1 || num > 0x7b || rx_buf[6] != num * 2){error_code = 3;break;}if (addr + num > MB_HOLDING_NUM){error_code = 2;break;}for (ind = 0; ind < 6; ind++){tx_buf[ind] = rx_buf[ind];}for (int i = 0; i < num; i++){val = (rx_buf[7 + 2 * i] << 8) | rx_buf[7 + 2 * i + 1];if (0 != mb_write_holding_cb(addr + i, val))error_code = 4;}crc16 = CRC16_ModBus(tx_buf, ind);tx_buf[ind++] = crc16;tx_buf[ind++] = crc16 >> 8;break;default:if (rx_buf[1] & 0x80)return 0;elseerror_code = 1;break;}if (error_code != 0){ind = 0;tx_buf[ind++] = DEV_ADDR;tx_buf[ind++] = rx_buf[1] | 0x80;tx_buf[ind++] = error_code;crc16 = CRC16_ModBus(tx_buf, ind);tx_buf[ind++] = crc16;tx_buf[ind++] = crc16 >> 8;}return ind;
}

2. rs_485_test.c

#include <rtthread.h>
#include <rtdevice.h>/* 串口设备句柄 */
static rt_device_t serial;/* 485控制引脚 */
static rt_base_t rs485_ctrl_pin = -1;/* timeout receive */
static int serial_read_frame(rt_device_t dev, uint8_t *buf, int max_len, uint32_t idle_ms, int timeout_ms)
{int rx_len = 0, rc;uint32_t idle_time, timeout_time, cur_tick, last_tick;timeout_time = rt_tick_from_millisecond(timeout_ms);idle_time = rt_tick_from_millisecond(idle_ms);cur_tick = rt_tick_get();while ((rt_tick_get() - last_tick < idle_time && rx_len < max_len) || rx_len <= 0){rc = rt_device_read(dev, rx_len, buf, max_len - rx_len);if (rc > 0){rx_len += rc;last_tick = rt_tick_get();}else{rt_thread_mdelay(1);}if (rt_tick_get() - cur_tick > timeout_time && rx_len <= 0)break;}return rx_len;
}
/* transmit with auto 485 pin ctrl */
static void serial_write_frame_rs485(rt_device_t dev, uint8_t *buf, int len, int bitrate, int ctrl_pin)
{int ms = len * 10 * 1000 / bitrate + 2;rt_pin_write(rs485_ctrl_pin, 1);rt_hw_us_delay(10);rt_device_write(dev, 0, buf, len);rt_thread_mdelay(ms);rt_pin_write(rs485_ctrl_pin, 0);
}static void serial_thread_entry(void *parameter)
{extern void mb_slave_init(unsigned char slave_addr, int coil_num, int di_num, int holding_num, int input_num);extern int mb_slave_process(unsigned char *rx_buf, int rx_len, unsigned char *tx_buf);rt_uint32_t rx_len, tx_len;static unsigned char rx_buf[260];static unsigned char tx_buf[260];mb_slave_init(1,16,16,32,32);while (1){rx_len = serial_read_frame(serial, rx_buf, 260, 10, 1000);if (rx_len <= 0)continue;tx_len = mb_slave_process(rx_buf, rx_len, tx_buf);if(tx_len>0)serial_write_frame_rs485(serial, rx_buf, rx_len, 115200, rs485_ctrl_pin);/* 打印数据 */rx_buf[rx_len] = '\0';rt_kprintf("rx_len = %d\n", rx_len);}
}static int uart_485_sample(int argc, char *argv[])
{rt_err_t ret = RT_EOK;char uart_name[RT_NAME_MAX] = "uart4";if (argc == 2){rt_strncpy(uart_name, argv[1], RT_NAME_MAX);}rt_kprintf("uart_name = %s\n", uart_name);if (rt_strcmp(uart_name,"uart3") == 0){rs485_ctrl_pin = rt_pin_get("PE.15");rt_pin_mode(rs485_ctrl_pin, PIN_MODE_OUTPUT);rt_pin_write(rs485_ctrl_pin, 0);}else if (rt_strcmp(uart_name,"uart4") == 0){rs485_ctrl_pin = rt_pin_get("PA.15");rt_pin_mode(rs485_ctrl_pin, PIN_MODE_OUTPUT);rt_pin_write(rs485_ctrl_pin, 0);}else{return RT_ERROR;}/* 查找串口设备 */serial = rt_device_find(uart_name);if (!serial){rt_kprintf("find %s failed!\n", uart_name);return RT_ERROR;}/* 以 DMA 接收及轮询发送方式打开串口设备 */rt_device_open(serial, RT_DEVICE_FLAG_RX_NON_BLOCKING | RT_DEVICE_FLAG_TX_NON_BLOCKING);/* 创建 serial 线程 */rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);/* 创建成功则启动线程 */if (thread != RT_NULL){rt_thread_startup(thread);}else{ret = RT_ERROR;}return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(uart_485_sample, uart device rs485 sample);

经实验测试,总体性能还错。对于简单Modbus设备,基本可以满足要求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/611067.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 车联网——其他Service介绍(十七)

除了前面介绍的 Service 和 Manager 之外,CarService 中还提供了很多其他 Service 和 Manager。 1、CarInputService CarInputService 是一个安卓汽车平台中的服务,它负责处理与车辆输入设备相关的操作,例如处理车辆上的按钮、方向盘控制、触摸屏输入等。该服务允许…

常用工具集合

摘要&#xff1a;更换电脑进行工具迁移&#xff0c;做一个记录。 1、前端 vscode plugins&#xff1a;Chinese (Simplified) (简体中文) Easy Sass: scss编辑生成css文件 Live Server: Launch a local development server with live reload 2、后端 idea 3、移动端 Android …

【Java集合篇】 ConcurrentHashMap在哪些地方做了并发控制

ConcurrentHashMap在哪些地方做了并发控制 ✅典型解析✅初始化桶阶段&#x1f7e2;桶满了会自动扩容吗&#x1f7e0;自动扩容的时间频率是多少 ✅put元素阶段✅扩容阶段&#x1f7e0; 拓展知识仓&#x1f7e2;ConcurrentSkipListMap和ConcurrentHashMap有什么区别☑️简单介绍一…

解决录制的 mp4 视频文件在 windows 无法播放的问题

解决录制的 mp4 视频文件在 windows 无法播放的问题 kazam 默认录制保存下来的 mp4 视频文件在 windows 中是无法直接使用的&#xff0c;这是由于视频编码方式的问题。解决办法&#xff1a; 首先安装 ffmeg 编码工具&#xff1a; sudo apt-get install ffmpeg 然后改变视频的…

BIND DNS 自定义zabbix监控

一、DNS统计计数器 Bind9可以使用rndc stats 命令将相关DNS统计信息存储到工作目录下&#xff0c;默认位置在&#xff1a; statistics-file "/var/named/data/named_stats.txt"; 每当名称服务器执行rndc stats命令&#xff0c;都会统计在统计信息文件最后附加一…

极少数据就能微调大模型,一文详解LoRA等方法的运作原理

原文&#xff1a;极少数据就能微调大模型&#xff0c;一文详解LoRA等方法的运作原理 最近和大模型一起爆火的&#xff0c;还有大模型的微调方法。 这类方法只用很少的数据&#xff0c;就能让大模型在原本表现没那么好的下游任务中“脱颖而出”&#xff0c;成为这个任务的专家…

【Python机器学习】SVM——一些理论知识

向数据中添加非线性特征&#xff0c;可以让线性模型变得强大&#xff0c;但是通常来说我们不知道要添加哪些特征&#xff0c;而且添加许多特征的计算开销会很大。有一种技巧可以在更高维度中学习分类器&#xff0c;而不用实际计算可能非常大的新的数据表示&#xff0c;这种技巧…

第87讲:XtraBackup备份工具的核心技术要点及全库备份、恢复案例

文章目录 1.XtraBackup备份工具的简介2.XBK备份工具的安装3.XBK备份工具的使用语法4.XBK备份前的准备5.使用XBK对全库进行备份5.1.XBK备份全库数据的语法格式5.2.使用XBK进行全库备份5.3.查看XBK备份的数据文件5.4.备份过程中生产的XBK文件 6.模拟故障案例并使用XBK恢复备份的数…

Vue 对象删除没有值的项

在调用后端查询接口时&#xff0c;有的要求参数对象里空值的项不要传&#xff0c;这个时候可以封装一个方法在调用接口前将对象过滤一遍。 1.新建一个名为tools.js的文件&#xff0c;里面放入以下代码 //对象删除没有值的项 export const removePropertyOfNull (obj) > { …

【React】常见疑问的整理

1. React渲染一个列表&#xff0c;需要为每一项指定key&#xff1f; 列表的key主要是为了react渲染阶段更好的协调&#xff08;reconciliation&#xff09;&#xff0c;diff时更好的识别react元素&#xff0c;减少dom的创建和操作&#xff0c;提升效率。 设定key值方式&#x…

openssl3.2 - 官方dmeo学习 - server-arg.c

文章目录 openssl3.2 - 官方dmeo学习 - server-arg.c概述笔记备注END openssl3.2 - 官方dmeo学习 - server-arg.c 概述 TLS服务器, 等客户端来连接; 如果客户端断开了, 通过释放bio来释放客户端socket, 然后继续通过bio读来aceept. 笔记 对于开源工程, 不可能有作者那么熟悉…

Python操作excel-读取、表格填充颜色区分

1.场景分析 遇到一个需要读取本地excel数据&#xff0c;处理后打入到数据库的场景&#xff0c;使用java比较重&#xff0c;python很好的解决了这类问题 2.重难点 本场景遇到的重难点在于&#xff1a; 需要根据表格内的背景颜色对数据进行筛选 读取非默认Sheet 总是出现Value…

Android Framework 常见解决方案(26)user版本可root方案

1 原理说明 User版本默认是没有root权限和remount功能的&#xff0c;一般该方法用于调试性能相关问题。如果使用debug版本对照&#xff0c;差异过大&#xff0c;因此就有了这样的需求。 修改的核心原理就是调整adbd及相关属性中的一些判定&#xff0c;即user和debug版本的区别…

C 语言关于sizeof() 和 strlen()区别?

sizeof() 和 strlen() 在 C 语言中两个非常常用&#xff0c;它们都与计算内存大小有关&#xff0c;但是它们的作用是不同的。 sizeof() 和 strlen() 的主要区别在于&#xff1a; sizeof() 是一个运算符&#xff0c;而 strlen() 是一个函数。sizeof() 计算的是变量或类型所占用…

day-05 删除子串后的字符串最小长度

思路 通过不断地检查是否含有"AB"或"CD"&#xff0c;如果有则将其从字符串中删除&#xff0c;直到"AB"或"CD"都不存在时&#xff0c;返回字符串的长度 解题方法 //检测是否有"AB" for(int i0;i<len-1;i){ if(s.charAt(i…

Python画国旗

前言 今天&#xff0c;我们来用turtle库来绘制国旗 一、美国国旗 国旗的形状是长方形;国旗的长宽之比为19:10&#xff0c;美国国旗由红、白、蓝三色组成;画面格局由两部分组成&#xff0c;旗的左上方蓝底上排列着50颗白色的星&#xff0c;6颗一排与5颗一排相间排列&#xff…

鸿蒙开发已解决-ArkTS开发webview,html页面中的input和按钮等操作均无响应

文章目录 项目场景:问题描述原因分析:解决方案(根据此方法即可解决此Bug):本文相关知识本Bug常规排除步骤ArkTS项目场景: 在鸿蒙开发过程遇到的问题: 问题 ArkTS API9 使用webview加载的html,页面中的按钮和input等操作均无响应 是有相关API设置webview是否可以touch或…

STM32(Cortex-M) 双堆栈MSP/PSP科普

https://blog.csdn.net/Guet_Kite/article/details/76020069 https://blog.csdn.net/zhuimeng_ruili/article/details/118163303 MSP/PSP是什么?作用&#xff1f; MSP主堆栈指针&#xff0c;PSP进程堆栈指针。 MSP&#xff1a;复位后缺省使用的堆栈指针&#xff0c;用于操作…

创建一个郭德纲相声GPTs

前言 在这篇文章中&#xff0c;我将分享如何利用ChatGPT 4.0辅助论文写作的技巧&#xff0c;并根据网上的资料和最新的研究补充更多好用的咒语技巧。 GPT4的官方售价是每月20美元&#xff0c;很多人并不是天天用GPT&#xff0c;只是偶尔用一下。 如果调用官方的GPT4接口&…

K8S存储卷和数据卷

容器内的目录和宿主机的目录进行挂载 容器在系统上的生命周期是短暂的&#xff0c;delete&#xff0c;k8s用控制器创建的pod&#xff0c;delete相当于重启&#xff0c;容器的状态也会恢复到初始状态&#xff0c;一旦回到初始状态&#xff0c;所有的后天编辑的文件都会消失 容器…