STM32G0开发笔记-Platformio+libopencm3-FreeRTOS和FreeModbus库使用

news2024/11/19 22:40:10

title: STM32G0开发笔记-Platformio+libopencm3-FreeRTOS和FreeModbus库使用
tags:

  • STM32
  • MCU
  • STM32G070
  • libopencm3
  • MonkeyPi
  • FreeRTOS
  • Modbus
    categories:
    • STM32
      date: 2022-9-11 19:52:05

[原文:makerinchina.cn]

使用Platformio平台的libopencm3开发框架来开发STM32G0,以下为FreeRTOS和FreeModbus库使用。

1 新建项目

  • 建立freertos_modbus项目

在PIO的Home页面新建项目,项目名称freertos_modbus,选择开发板为 MonkeyPi_STM32_G070RB,开发框架选择libopencm3;

  • 项目建立完成后在src目录下新建main.c主程序文件;
  • 修改下载和调试方式,这里开发板使用的是DAPLink仿真器,因此修改platformio.ini文件如下:
upload_protocol = cmsis-dap
debug_tool = cmsis-dap

2 编写程序

直接在之前的FreeRTOS工程上进行添加;

2.1 添加 freeModbus 库

从git仓库下载源码: https://github.com/cwalter-at/freemodbus

将下载的源码中的mobus文件夹放置到工程的lib目录下,然后在modbus目录新建library.json文件,内容如下:

{
    "name": "FreeModbus",
    "version": "master",
    "repository":{
        "type":"git",
        "url":"https://github.com/cwalter-at/freemodbus"
    },
    "build": {
        "flags": [
            "-Iascii",
            "-Ifunctions",
            "-Iinclude",
            "-Irtu",
            "-Itcp"
        ],
        "srcFilter": [
            "+<*>"
        ]
    }
}

然后从FreeModbus源码中的 demo\BARE\port中复制文件到工程的src\modbus_port文件夹下,最后的文件夹结构如下:

在这里插入图片描述

2.2 移植
  • portevent:
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"
#include "FreeRTOS.h"
#include "task.h"

/* ----------------------- Variables ----------------------------------------*/
static eMBEventType eQueuedEvent;
static BOOL     xEventInQueue;
static uint32_t modbus_last_active_time = 0;

uint32_t get_modbus_last_active_time(void)
{
	return modbus_last_active_time;
}

/* ----------------------- Start implementation -----------------------------*/
BOOL
xMBPortEventInit( void )
{
    xEventInQueue = FALSE;
    return TRUE;
}

BOOL
xMBPortEventPost( eMBEventType eEvent )
{
    xEventInQueue = TRUE;
    eQueuedEvent = eEvent;

	if (eEvent == EV_EXECUTE) {
		modbus_last_active_time = xTaskGetTickCount();
	}
    return TRUE;
}

BOOL
xMBPortEventGet( eMBEventType * eEvent )
{
    BOOL            xEventHappened = FALSE;

    if( xEventInQueue )
    {
        *eEvent = eQueuedEvent;
        xEventInQueue = FALSE;
        xEventHappened = TRUE;
    }
    return xEventHappened;
}
  • portserial

这里使用RS485,因此需要对RS485使能端口进行配置,其他为串口的配置,然后在发送和接收中断时候调用modbus相关接口进行处理:

#include "port.h"

#include "FreeRTOS.h"
#include "queue.h"

#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>

/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"

/* ----------------------- static functions ---------------------------------*/

xQueueHandle uart_queue;

#define RS485_1_CLOCK		RCC_GPIOB
#define RS485_1_EN_PORT		GPIOB
#define RS485_1_EN_PIN		GPIO8

static void rs485_delay(int n)
{
    while (--n) {
        __asm__ volatile ("nop");
    }
}

static inline void rs485_1_rx_mode(void)
{
    gpio_clear(RS485_1_EN_PORT, RS485_1_EN_PIN);
}

static inline void rs485_1_tx_mode(void)
{
    gpio_set(RS485_1_EN_PORT, RS485_1_EN_PIN);
}

static inline void rs485_gpio_init(void)
{
	rcc_periph_clock_enable(RS485_1_CLOCK);
	gpio_mode_setup(RS485_1_EN_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, RS485_1_EN_PIN);

	rs485_1_rx_mode();
}

/* ----------------------- Start implementation -----------------------------*/
void
vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )
{
    /* If xRXEnable enable serial receive interrupts. If xTxENable enable
     * transmitter empty interrupts.
     */
    if (xRxEnable) {
        rs485_delay(10000);
        rs485_1_rx_mode();
        rs485_delay(10000);
		usart_enable_rx_interrupt(USART1);
    }
    else {
		usart_disable_rx_interrupt(USART1);
    }
    
    if (xTxEnable) {
        rs485_delay(10000);
        rs485_1_tx_mode();
        rs485_delay(10000);
		usart_enable_tx_interrupt(USART1);
    }
    else {
		usart_disable_tx_interrupt(USART1);

    }
}

BOOL
xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity )
{
	nvic_enable_irq(NVIC_USART1_IRQ);

	rcc_periph_clock_enable(RCC_GPIOB);
	gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO6 | GPIO7);
	gpio_set_af(GPIOB, GPIO_AF0, GPIO6 | GPIO7);

	rcc_periph_clock_enable(RCC_USART1);

	/* Set up USART/UART parameters using the libopencm3 helper functions */
	usart_set_baudrate(USART1, ulBaudRate);
	usart_set_databits(USART1, ucDataBits);
	usart_set_stopbits(USART1, USART_STOPBITS_1);
	usart_set_mode(USART1, USART_MODE_TX_RX);

    switch (eParity) {
        case MB_PAR_ODD:
			usart_set_parity(USART1, USART_PARITY_ODD);
            break;
        case MB_PAR_EVEN:
			usart_set_parity(USART1, USART_PARITY_EVEN);
            break;
        default:
			usart_set_parity(USART1, USART_PARITY_NONE);
            break;
    }

	usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE);

	usart_enable(USART1);

    rs485_gpio_init();

    return TRUE;
}

BOOL
xMBPortSerialPutByte( CHAR ucByte )
{

    usart_send_blocking(USART1, (uint16_t) ucByte);    
    
    return TRUE;
}

BOOL
xMBPortSerialGetByte( CHAR * pucByte )
{
	*pucByte = usart_recv(USART1);

    return TRUE;
}


uint32_t uart1_isr, uart1_icr;

void usart1_isr(void)
{

	/* Check if we were called because of RXNE. */
	if (((USART_CR1(USART1) & USART_CR1_RXNEIE) != 0) &&
	    ((USART_ISR(USART1) & USART_ISR_RXNE) != 0)) {

		/* Retrieve the data from the peripheral. */
        // usart_recv(USART1);

		pxMBFrameCBByteReceived();

	}


	/* Check if we were called because of TXE. */
	if (((USART_CR1(USART1) & USART_CR1_TXEIE) != 0) &&
	    ((USART_ISR(USART1) & USART_ISR_TXE) != 0)) {

		/* Put data into the transmit register. */
		//usart_send(USART1, data);

		pxMBFrameCBTransmitterEmpty();

	}

}
  • porttimer
#include "port.h"

#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/timer.h>

/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"

/* ----------------------- static functions ---------------------------------*/
static void prvvTIMERExpiredISR( void );

/* ----------------------- Start implementation -----------------------------*/
BOOL
xMBPortTimersInit( USHORT usTim1Timerout50us )
{
	rcc_periph_clock_enable(RCC_TIM2);
	nvic_enable_irq(NVIC_TIM2_IRQ);
	rcc_periph_reset_pulse(RST_TIM2);

	timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);

	timer_set_prescaler(TIM2, (rcc_apb1_frequency/ 20000));

	timer_disable_preload(TIM2);
	timer_continuous_mode(TIM2);

	timer_set_period(TIM2, usTim1Timerout50us);
	timer_enable_counter(TIM2);

	timer_enable_irq(TIM2, TIM_DIER_UIE);

    return TRUE;
}


inline void
vMBPortTimersEnable(  )
{
	timer_set_counter(TIM2, 0);
	timer_enable_counter(TIM2);
}

inline void
vMBPortTimersDisable(  )
{
	timer_disable_counter(TIM2);
}

/* Create an ISR which is called whenever the timer has expired. This function
 * must then call pxMBPortCBTimerExpired( ) to notify the protocol stack that
 * the timer has expired.
 */
static void prvvTIMERExpiredISR( void )
{
    ( void )pxMBPortCBTimerExpired(  );
}

void
vMBPortTimersDelay( USHORT usTimeOutMS )
{
    vTaskDelay(pdMS_TO_TICKS(usTimeOutMS));
}

void tim2_isr(void)
{
	if (timer_get_flag(TIM2, TIM_SR_UIF)) {

		/* Clear compare interrupt flag. */
		timer_clear_flag(TIM2, TIM_SR_UIF);

        prvvTIMERExpiredISR();

	}
}

开启定时器和中断,用于modbus时序控制;

2.3 使用

在src目录新建 modbus_cb.h 和 modbus_cb.c 两个文件,实现寄存器、线圈的读写回调:

/// CMD4
eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs );

/// CMD6、3、16
eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode );

/// CMD1、5、15
eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode );

/// CMD4
eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete );

基本的实现示例如下:

#include "modbus_cb.h"
#include "stdbool.h"

extern log(const char* fmt, ...);

// 输入寄存器
#define REG_INPUT_SIZE  32
uint16_t REG_INPUT_BUF[REG_INPUT_SIZE];

// 保持寄存器
#define REG_HOLD_SIZE   32
uint16_t REG_HOLD_BUF[REG_HOLD_SIZE];

// 线圈寄存器
#define REG_COILS_SIZE 16
uint8_t REG_COILS_BUF[REG_COILS_SIZE];

// 离散量
#define REG_DISC_SIZE  8
uint8_t REG_DISC_BUF[REG_DISC_SIZE];

/// CMD4
eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
    USHORT usRegIndex = usAddress - 1; 

	// 非法检测
	if((usRegIndex + usNRegs) > REG_INPUT_SIZE)
	{
		return MB_ENOREG;
	}

    log(" CMD4, 寄存器输入.");

	// 填充数据
    REG_INPUT_BUF[0] = 0x01;
	REG_INPUT_BUF[1] = 0x02;

    // 循环读取
	while ( usNRegs > 0 ) {
		*pucRegBuffer++ = ( unsigned char )( REG_INPUT_BUF[usRegIndex] >> 8 );
		*pucRegBuffer++ = ( unsigned char )( REG_INPUT_BUF[usRegIndex] & 0xFF );
		usRegIndex++;
		usNRegs--;
	}

	return MB_ENOERR;
}

/// CMD6、3、16
eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
{
    USHORT usRegIndex = usAddress - 1;  

	// 非法检测
	if((usRegIndex + usNRegs) > REG_HOLD_SIZE) {
		return MB_ENOREG;
	}

    log(" CMD3,6,16, 保持寄存器读写.");
    
	// 写寄存器
	if (eMode == MB_REG_WRITE) {
		while ( usNRegs > 0 ) {
			uint16_t value;

			value = (pucRegBuffer[0] << 8) | pucRegBuffer[1];

			log("  写寄存器值:%d", value);

			pucRegBuffer += 2;
			usRegIndex++;
			usNRegs--;

        }

    }
    // 读寄存器
	else {

		log("  读寄存器.");
		
		REG_HOLD_BUF[0] = 0x32;
		REG_HOLD_BUF[1] = 0x33;

        while ( usNRegs > 0 ) {
			*pucRegBuffer++ = ( unsigned char )( REG_HOLD_BUF[usRegIndex] >> 8 );
			*pucRegBuffer++ = ( unsigned char )( REG_HOLD_BUF[usRegIndex] & 0xFF );
			usRegIndex++;
			usNRegs--;
		}
	}

	return MB_ENOERR;
}

/// CMD1、5、15
eMBErrorCode eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
{

    USHORT usRegIndex   = usAddress - 1;
	USHORT usCoilGroups = ((usNCoils - 1) / 8 + 1);
	UCHAR  ucStatus     = 0;
	UCHAR  ucBits       = 0;
	UCHAR  ucDisp       = 0;

	// 非法检测
	if ((usRegIndex + usNCoils) > REG_COILS_SIZE) {
		return MB_ENOREG;
	}

    log("  CMD1,5,15, 线圈读写.");

	// 写线圈
	if (eMode == MB_REG_WRITE) {

		while (usCoilGroups--) {

			ucStatus = *pucRegBuffer++;
			ucBits   = 8;

			while((usNCoils) != 0 && (ucBits) != 0) {
				bool flag = ucStatus & 0x01;

				switch (usRegIndex) {
					
                    case 0:
						log(" 线圈0 : %d", flag);//
                    break;

					case 1:
						log(" 线圈1 : %d", flag);
					break;

					default:

					break;

				}

				usRegIndex++;
				ucStatus >>= 1;
				usNCoils--;
				ucBits--;
			}

		}
	}
    // 读线圈
	else {
		
		REG_COILS_BUF[0]  = 1;
		REG_COILS_BUF[1]  = 0;

		while (usCoilGroups--) {
			ucDisp = 0;
			ucBits = 8;
			ucStatus = 0;

			while((usNCoils) != 0 && (ucBits) != 0) {
				ucStatus |= (REG_COILS_BUF[usRegIndex++] << (ucDisp++));
				usNCoils--;
				ucBits--;
			}

			*pucRegBuffer++ = ucStatus;
		}
	}

	return MB_ENOERR;
}

/// CMD4
eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
    USHORT usRegIndex   = usAddress - 1;
	USHORT usCoilGroups = ((usNDiscrete - 1) / 8 + 1);
	UCHAR  ucStatus     = 0;
	UCHAR  ucBits       = 0;
	UCHAR  ucDisp       = 0;

	// 非法检测
	if ((usRegIndex + usNDiscrete) > REG_DISC_SIZE) {
		return MB_ENOREG;
	}

    log("  CMD4, 离散寄存器写入.");

	// 读离散输入
	while (usCoilGroups--) {
		ucDisp = 0;
		ucBits = 8;
		ucStatus = 0;

		while((usNDiscrete != 0) && (ucBits != 0))
		{
			switch (usRegIndex) {
			case 0:
				ucStatus = 0x10;
				break;
			}

			usRegIndex++;
			ucDisp++;
			usNDiscrete--;
			ucBits--;
		}
		*pucRegBuffer++ = ucStatus;
	}

    	return MB_ENOERR;
}

在main中创建modbus任务:

static void task_modbus_handle(void *param)
{

    eMBErrorCode    eStatus;

    log("  task modbus start.");

    eStatus = eMBInit( MB_RTU, 0x01, 0, 9600, MB_PAR_NONE );

    /* Enable the Modbus Protocol Stack. */
    eStatus = eMBEnable();

	(void)eStatus;

    for( ;; ) {
        ( void )eMBPoll();
        vTaskDelay(pdMS_TO_TICKS(10));
    }

}

3 烧写测试

将开发板连接到USB转485模块,然后使用modbus poll程序进行测试:

在这里插入图片描述

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

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

相关文章

docker -- 入门篇 (数据卷、自定义镜像、安装mysql redis)

1 数据卷 采用上一章节创建的centos镜像启动容器 doc01 docker run -it --name doc01 lhy/centos:1.00 2 数据卷容器 启动子容器doc02 实现继承doc01的关系 docker run -it --name doc02 --volumes-from doc01 lhy/centos:1.00 启动子容器doc03 实现继承doc01的关系 docker…

【计算机毕业设计】病人跟踪治疗信息管理系统源码

一、系统截图&#xff08;需要演示视频可以私聊&#xff09; 摘 要 病人跟踪治疗信息管理系统采用B/S模式&#xff0c;促进了病人跟踪治疗信息管理系统的安全、快捷、高效的发展。传统的管理模式还处于手工处理阶段&#xff0c;管理效率极低&#xff0c;随着病人的不断增多&a…

mac pro M1(ARM)安装:安装zookeeper可视化工具PrettyZoo、ZooKeeperAssistant

0. 引言 今天安装zookeeper的可视化工具遇到一些问题&#xff0c;将其记录下来&#xff0c;以供后续的同学参考&#xff0c;在mac软件安装上少走弯路。同时也让大家体会下这两款不同的zk可视化工具的差别 1. 安装PrettyZoo 1、下载 直接在github上选择版本下载&#xff1a; …

8 - 复习总结java中的继承与多态

1. 继承 1.1 为什么需要继承 先看一个例子: 比如猫和狗都是动物&#xff0c;都可以用一个类来描述。 使用java语言来描述&#xff1a; class Cat{String name;int age;float wight;public void bark(){System.out.println(name"汪汪汪叫");}public void eat(){S…

PyTorch使用快速梯度符号攻击(FGSM)实现对抗性样本生成(附源码和数据集MNIST手写数字)

需要源码和数据集请点赞关注收藏后评论区留言或者私信~~~ 一、威胁模型 对抗性机器学习&#xff0c;意思是在训练的模型中添加细微的扰动最后会导致模型性能的巨大差异&#xff0c;接下来我们通过一个图像分类器上的示例来进行讲解&#xff0c;具体的说&#xff0c;会使用第一…

Reactor 模型

文章目录1、网络编程关注的事件2、网络 IO 的职责2.1、IO 检测2.1.1、连接建立2.1.2、连接断开2.1.3、消息到达2.1.4、消息发送2.2、IO 操作2.2.1、连接建立2.2.2、连接断开2.2.3、连接到达2.2.4、消息发送3、Reactor 模式3.1、概念3.2、面试&#xff1a;Reactor 为什么使用非阻…

利用jenkins直接构件docker镜像并发布

一、本服务器构建 1.jenkins安装完成之后&#xff0c;打jenkins&#xff0c;选择新建任务&#xff0c;如&#xff1a; 2.进行〔源码管理〕配置&#xff0c;如&#xff1a; 3.构建执行配置&#xff0c;如&#xff1a; APP_NAMEtest-project APP_PORT8083 RUN_ENVprod cd /var/…

EtherCAT与RTEX驱动器轴回零的配置与实现

上节课程&#xff0c;正运动小助手给大家分享了运动控制器提供的回零模式配置与实现。本节课程主要介绍控制器实现EtherCAT与RTEX驱动器的回零及其配置。 01 总线驱动器回零模式 正运动控制器提供自己的回零模式&#xff0c;也支持使用EtherCAT总线驱动器提供的回零模式&…

学长教你学C-day9-C语言循环结构与选择结构

小刘最近在读《老子》&#xff0c;被道家“一生二&#xff0c;二生三”的哲学思想迷住了&#xff0c;他不禁想代码是谁生的呢&#xff1f;首先代码就是一堆字符&#xff0c;字符不是代码&#xff0c;就像“白马非马”&#xff0c;但是当字符按照一定的顺序组织起来时&#xff0…

《Python编程无师自通》读书笔记

不能越界访问函数内部定义的变量 global不能乱用 啥时候用元组 join连接 小点&#xff0c;但第一次见会觉得蛮有意思。 Hangman 10.1的案例蛮有意思的 一搜才发现是十分经典的文字游戏 过程式编程的缺点以及函数式编程和面向对象编程的解决方法 过程式编程的缺点 函数式编程…

Web学习笔记-中期项目(拳皇)

CONTENTS项目原理一、基础文件二、ac_game_object框架三、游戏地图与玩家模型的创建项目原理 游戏中一个物体运动的原理是浏览器每秒钟刷新60次&#xff0c;每次我们单独计算这个物体新的位置&#xff0c;然后把他刷新出来&#xff0c;这样最终人眼看起来就是移动的效果。 对…

YOLO系列概述(yolov1至yolov7)

YOLO系列概述&#xff08;yolov1至yolov7&#xff09; 参考&#xff1a; 睿智的目标检测53——Pytorch搭建YoloX目标检测平台YoloV7 yolo的发展历史 首先我们来看一下yolo系列的发展历史&#xff0c;yolo v1和yolox是anchor free的方法&#xff0c;yolov2&#xff0c;yolov3…

使用 Vue3 实现锚点组件

目录 1. 需求介绍 2. 实现过程 2.1 表单结构介绍 2.2 确定锚点组件接收的参数及使用方法 2.2.1 form-dom&#xff1a;需要被锚点组件控制的表单实例 2.2.2 active-anchor&#xff1a;默认激活的锚点 2.2.3 title-class&#xff1a;表单标题特有的类名 2.2.4 将 锚点组件…

5-FITC,5-FITC(isomer I),5-异硫氰酸荧光素,5-Flourescein iso-thiocyanate

产品名称&#xff1a;5-FITC&#xff0c;5-异硫氰酸荧光素 英文名称&#xff1a;5-Flourescein iso-thiocyanate 英文别名&#xff1a;5-FITC&#xff1b;5-Flourescein iso-thiocyanate&#xff1b;FITC Isomer I [5-FITC; fluorescein-5-isothiocyanate] CAS#&#xff1a;…

labview 串口通信 modbusRtu

在自动化或测试项目中&#xff0c;上位机软件需要和PLC及仪表通信&#xff0c;本文简单描述这个问题。 1.在程序框图中放置4个图标 &#xff08;1&#xff09;创建modbus 主站实例&#xff08;按如下图标识①,在框图中放Create Master Instance.vi) 图1 放置四个图标 &…

C++ Reference: Standard C++ Library reference: Containers: deque: deque: resize

C官网参考链接&#xff1a;https://cplusplus.com/reference/deque/deque/resize/ 公有成员函数 <deque> std::deque::resize C98 void resize (size_type n, value_type val value_type()); C11 void resize (size_type n); void resize (size_type n, const value_t…

React组件复用

mixins&#xff08;已废弃&#xff09; https://react.docschina.org/blog/2016/07/13/mixins-considered-harmful.html mixin引入了隐式依赖关系 对于组件中的方法和数据的来源不明确&#xff0c;不容易维护 Mixins 导致名称冲突Mixins 导致滚雪球般的复杂性 render-props技术…

C语言学习之路(基础篇)—— 指针(上)

说明&#xff1a;该篇博客是博主一字一码编写的&#xff0c;实属不易&#xff0c;请尊重原创&#xff0c;谢谢大家&#xff01; 概述 1) 内存 内存含义&#xff1a; 存储器&#xff1a; 计算机的组成中&#xff0c;用来存储程序和数据&#xff0c;辅助CPU进行运算处理的重要…

python切分TXT的句子到Excel(复制可用)——以及python切分句子遇到的问题汇总

文章目录完整代码时间转化和提取各种对象类型转换时间序列类属性数据转换完整代码 import jieba.analyseimport jieba.posseg as pseg from wordcloud import WordCloud import xlsxwriter # encodinggbk import xlsxwriterf open(E:/data/xieyangteng/review.txt, r, encodi…

波的相关参数概念整理

频率&#xff08;frequency&#xff09;&#xff0c;符号f&#xff0c;表示单位时间内完成周期性变化的次数。f1/T&#xff0c;单位s-1 角频率&#xff0c;符号ω&#xff0c;表示单位时间内变化的角弧度值。ω 2πf 2π/T,单位rad/s 波长&#xff08;wavelength&#xff0…