stm32 输入捕获 测量脉宽

选用通用定时器TIM5的CH1。

PA0接一个按键,默认接GND,当按键按下时,IO口被拉高,此时,可利用定时器的输入捕获功能,测量按键按下的这段高电平的时间。

在这里插入图片描述

宏定义方便程序升级、移植,举个例子:

输入捕获通道 GPIO 初始化,里面有一个GENERAL_TIM_CH1_GPIO_CLK,这个东西是个宏定义。使用不同GPIO的时候,只需要修改头文件里面的宏定义,不需要修改这个函数。

// TIM 输入捕获通道GPIO相关宏定义
#define            GENERAL_TIM_CH1_GPIO_CLK      RCC_APB2Periph_GPIOA
static void GENERAL_TIM_GPIO_Config(void) 
{GPIO_InitTypeDef GPIO_InitStructure;// 输入捕获通道 GPIO 初始化RCC_APB2PeriphClockCmd(GENERAL_TIM_CH1_GPIO_CLK, ENABLE);GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH1_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GENERAL_TIM_CH1_PORT, &GPIO_InitStructure);	
}

下面是宏定义。

#ifndef __BSP_GENERALTIME_H
#define __BSP_GENERALTIME_H#include "stm32f10x.h"/************通用定时器TIM参数定义,只限TIM2、3、4、5************/
// 当使用不同的定时器的时候,对应的GPIO是不一样的,这点要注意
// 我们这里默认使用TIM5#define            GENERAL_TIM                   TIM5
#define            GENERAL_TIM_APBxClock_FUN     RCC_APB1PeriphClockCmd
#define            GENERAL_TIM_CLK               RCC_APB1Periph_TIM5
#define            GENERAL_TIM_PERIOD            0XFFFF
#define            GENERAL_TIM_PSC              (72-1)// TIM 输入捕获通道GPIO相关宏定义
#define            GENERAL_TIM_CH1_GPIO_CLK      RCC_APB2Periph_GPIOA
#define            GENERAL_TIM_CH1_PORT          GPIOA
#define            GENERAL_TIM_CH1_PIN           GPIO_Pin_0
#define            GENERAL_TIM_CHANNEL_x         TIM_Channel_1// 中断相关宏定义
#define            GENERAL_TIM_IT_CCx            TIM_IT_CC1
#define            GENERAL_TIM_IRQ               TIM5_IRQn
#define            GENERAL_TIM_INT_FUN           TIM5_IRQHandler// 获取捕获寄存器值函数宏定义
#define            GENERAL_TIM_GetCapturex_FUN                 TIM_GetCapture1
// 捕获信号极性函数宏定义
#define            GENERAL_TIM_OCxPolarityConfig_FUN           TIM_OC1PolarityConfig// 测量的起始边沿
#define            GENERAL_TIM_STRAT_ICPolarity                TIM_ICPolarity_Rising
// 测量的结束边沿
#define            GENERAL_TIM_END_ICPolarity                  TIM_ICPolarity_Falling// 定时器输入捕获用户自定义变量结构体声明
typedef struct
{   uint8_t   Capture_FinishFlag;   // 捕获结束标志位uint8_t   Capture_StartFlag;    // 捕获开始标志位uint16_t  Capture_CcrValue;     // 捕获寄存器的值uint16_t  Capture_Period;       // 自动重装载寄存器更新标志 
}TIM_ICUserValueTypeDef;extern TIM_ICUserValueTypeDef TIM_ICUserValueStructure;/**************************函数声明********************************/
void GENERAL_TIM_Init(void);#endif	/* __BSP_GENERALTIME_H */

下面GENERAL_TIM_Mode_Config是定时器模式配置。

里面初始化了两个结构体。

对于时基结构体:

1.GENERAL_TIM_PERIOD配置ARR寄存器的值,决定计数器一个周期的计数时间,默认配置为0XFFFF(65535),即最大。


自动重装载寄存器ARR:16位寄存器,这里面装着计数器能计数的最大数值。当计数到这个值的时候,如果使能了中断,定时器就产生溢出中断。

CNT是16位的计数器,只能往上计数,最大计数值为65535。当计数达到自动重装载寄存器的时候产生更新事件,并清零从头开始计数


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JOmOfWyS-1646185240167)(stm32 输入捕获 测量脉宽.assets/Snipaste_2022-02-27_10-49-11.png)]

时钟源:定时器时钟TIMxCLK,即内部时钟CK_INT,经APB1预分频器分频提供。

APB1预分频系数等于1,频率不变。

库函数中APB1预分频的系数是2,即PCLK1=36M,所以定时器时钟TIMxCLK=36*2=72M

计数器时钟CK_CNT

定时器时钟经过PSC预分频器后,即CK_CNT,用来驱动计数器计数。

PSC是16位的预分频器,可以对定时器时钟TIMxCLK进行1~65536之间的任何一个数进行分频。CK_CNT=TIMxCLK/(PSC+1)

2.GENERAL_TIM_PSC配置分频因子,默认配置为72-1。可以计算出计数器的计数周期为(GENERAL_TIM_PSC+1)/72M=1us。


当捕获通道TIx上出现上升沿时,发生第一次捕获。

计数器CNT的值,被锁存到捕获寄存器CCR中,进入捕获中断。

输入捕获能捕获的最小的时间为1us,最长的时间为1us *(0Xffff+1)=65536us=65.536ms。

超过这个计数周期的时候,产生中断,然后在中断里面做额外的处理。

需要记录好产生了多少次更新中断,最后把更新时间加入脉宽时间里面。


GENERAL_TIM_NVIC_Config是中断优先级配置。只有一个中断源,优先级可以随便配置。

#include "bsp_GeneralTim.h"// 定时器输入捕获用户自定义变量结构体定义
TIM_ICUserValueTypeDef TIM_ICUserValueStructure = {0,0,0,0};// 中断优先级配置
static void GENERAL_TIM_NVIC_Config(void)
{NVIC_InitTypeDef NVIC_InitStructure; // 设置中断组为0NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);		// 设置中断来源NVIC_InitStructure.NVIC_IRQChannel = GENERAL_TIM_IRQ ;	// 设置主优先级为 0NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;	 // 设置抢占优先级为3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}static void GENERAL_TIM_GPIO_Config(void) 
{GPIO_InitTypeDef GPIO_InitStructure;// 输入捕获通道 GPIO 初始化RCC_APB2PeriphClockCmd(GENERAL_TIM_CH1_GPIO_CLK, ENABLE);GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH1_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GENERAL_TIM_CH1_PORT, &GPIO_InitStructure);	
}///*
// * 注意:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有
// * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可,
// * 另外三个成员是通用定时器和高级定时器才有.
// *-----------------------------------------------------------------------------
// *typedef struct
// *{ TIM_Prescaler            都有
// *	TIM_CounterMode			     TIMx,x[6,7]没有,其他都有
// *  TIM_Period               都有
// *  TIM_ClockDivision        TIMx,x[6,7]没有,其他都有
// *  TIM_RepetitionCounter    TIMx,x[1,8,15,16,17]才有
// *}TIM_TimeBaseInitTypeDef; 
// *-----------------------------------------------------------------------------
// *//* ----------------   PWM信号 周期和占空比的计算--------------- */
// ARR :自动重装载寄存器的值
// CLK_cnt:计数器的时钟,等于 Fck_int / (psc+1) = 72M/(psc+1)
// PWM 信号的周期 T = ARR * (1/CLK_cnt) = ARR*(PSC+1) / 72M
// 占空比P=CCR/(ARR+1)static void GENERAL_TIM_Mode_Config(void)
{// 开启定时器时钟,即内部时钟CK_INT=72MGENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK,ENABLE);/*--------------------时基结构体初始化-------------------------*/	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM_PERIOD;	// 驱动CNT计数器的时钟 = Fck_int/(psc+1)TIM_TimeBaseStructure.TIM_Prescaler= GENERAL_TIM_PSC;	// 时钟分频因子 ,配置死区时间时需要用到TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;		// 计数器计数模式,设置为向上计数TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;		// 重复计数器的值,没用到不用管TIM_TimeBaseStructure.TIM_RepetitionCounter=0;	// 初始化定时器TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);/*--------------------输入捕获结构体初始化-------------------*/	TIM_ICInitTypeDef TIM_ICInitStructure;// 配置输入捕获的通道,需要根据具体的GPIO来配置TIM_ICInitStructure.TIM_Channel = GENERAL_TIM_CHANNEL_x;// 输入捕获信号的极性配置TIM_ICInitStructure.TIM_ICPolarity = GENERAL_TIM_STRAT_ICPolarity;// 输入通道和捕获通道的映射关系,有直连和非直连两种TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;// 输入的需要被捕获的信号的分频系数TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;// 输入的需要被捕获的信号的滤波系数TIM_ICInitStructure.TIM_ICFilter = 0;// 定时器输入捕获初始化TIM_ICInit(GENERAL_TIM, &TIM_ICInitStructure);// 清除更新和捕获中断标志位TIM_ClearFlag(GENERAL_TIM, TIM_FLAG_Update|GENERAL_TIM_IT_CCx);	// 开启更新和捕获中断  TIM_ITConfig (GENERAL_TIM, TIM_IT_Update | GENERAL_TIM_IT_CCx, ENABLE );// 使能计数器TIM_Cmd(GENERAL_TIM, ENABLE);
}void GENERAL_TIM_Init(void)
{GENERAL_TIM_GPIO_Config();GENERAL_TIM_NVIC_Config();GENERAL_TIM_Mode_Config();		
}

中断服务函数

在这里插入图片描述

输入捕获的起始边沿为GENERAL_TIM_STRAT_ICPolarity,这是一个宏,默认配置为上升沿。

// 测量的起始边沿
#define            GENERAL_TIM_STRAT_ICPolarity                TIM_ICPolarity_Rising

按键默认接GND,按键按下的时候被拉高,这个时候这个由低到高的上升沿被捕获到,这是第一次捕获。

此时把计数器清0,开始计数,同时把捕获边沿改成下降沿捕获。

第二次进入中断服务函数的时候,说明捕获到下降沿,这个时候表示脉宽捕获完毕。

读取捕获寄存器的值,然后可以通过这个值算出脉宽的时间。

最后,把捕获编译配置为上升沿,为的是下一次捕获。

脉宽的时间超过了计数器的最大计数时间,就会产生更新中断,需要记录产生了多少次更新中断。

最后算脉宽的时间的时候加上更新的时间。

中断服务函数里面,捕获结束标志位、捕获开始标志位、捕获寄存器的值、自动重装载更新标志,在一个结构体里面定义。

// 定时器输入捕获用户自定义变量结构体声明
typedef struct
{   uint8_t   Capture_FinishFlag;   // 捕获结束标志位uint8_t   Capture_StartFlag;    // 捕获开始标志位uint16_t  Capture_CcrValue;     // 捕获寄存器的值uint16_t  Capture_Period;       // 自动重装载寄存器更新标志 
}TIM_ICUserValueTypeDef;
void GENERAL_TIM_INT_FUN(void)
{// 当要被捕获的信号的周期大于定时器的最长定时时,定时器就会溢出,产生更新中断// 这个时候我们需要把这个最长的定时周期加到捕获信号的时间里面去if ( TIM_GetITStatus ( GENERAL_TIM, TIM_IT_Update) != RESET )               {	TIM_ICUserValueStructure.Capture_Period ++;		TIM_ClearITPendingBit ( GENERAL_TIM, TIM_FLAG_Update ); 		}// 上升沿捕获中断if ( TIM_GetITStatus (GENERAL_TIM, GENERAL_TIM_IT_CCx ) != RESET){// 第一次捕获if ( TIM_ICUserValueStructure.Capture_StartFlag == 0 ){// 计数器清0TIM_SetCounter(GENERAL_TIM, 0 );// 自动重装载寄存器更新标志清0TIM_ICUserValueStructure.Capture_Period = 0;// 存捕获比较寄存器的值的变量的值清0			TIM_ICUserValueStructure.Capture_CcrValue = 0;// 当第一次捕获到上升沿之后,就把捕获边沿配置为下降沿GENERAL_TIM_OCxPolarityConfig_FUN(GENERAL_TIM, TIM_ICPolarity_Falling);// 开始捕获标准置1			TIM_ICUserValueStructure.Capture_StartFlag = 1;			}// 下降沿捕获中断else // 第二次捕获{// 获取捕获比较寄存器的值,这个值就是捕获到的高电平的时间的值TIM_ICUserValueStructure.Capture_CcrValue = GENERAL_TIM_GetCapturex_FUN (GENERAL_TIM);// 当第二次捕获到下降沿之后,就把捕获边沿配置为上升沿,好开启新的一轮捕获GENERAL_TIM_OCxPolarityConfig_FUN(GENERAL_TIM, TIM_ICPolarity_Rising);// 开始捕获标志清0		TIM_ICUserValueStructure.Capture_StartFlag = 0;// 捕获完成标志置1			TIM_ICUserValueStructure.Capture_FinishFlag = 1;		}TIM_ClearITPendingBit (GENERAL_TIM,GENERAL_TIM_IT_CCx);	    }		
}

main函数里面,一些初始化,在一个while循环中打印测量的脉宽时间。

计算的时候,把周期GENERAL_TIMPERIOD和Capture_CcrValue的值都加1后再运算

#define            GENERAL_TIM_PSC              (72-1)
//CK_CNT=TIMxCLK/(PSC+1)
// TIM 计数器的驱动时钟,定时器时钟经过PSC预分频器后,即CK_CNT,用来驱动计数器计数。uint32_t TIM_PscCLK = 72000000 / (GENERAL_TIM_PSC+1);// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM_PERIOD;
#define            GENERAL_TIM_PERIOD            0XFFFFuint16_t  Capture_CcrValue;     // 捕获寄存器的值uint16_t  Capture_Period;       // 自动重装载寄存器更新标志
/*当要被捕获的信号的周期大于定时器的最长定时时,定时器就会溢出,产生更新中断
Capture_Period记录进入更新中断的次数*/

下面这个计算高电平时间的计数器的值,进入更新中断的次数*(自动重装载寄存器的值+1)+第二次捕获时,捕获比较寄存器的值+1。

// 计算高电平时间的计数器的值time = TIM_ICUserValueStructure.Capture_Period * (GENERAL_TIM_PERIOD+1) + (TIM_ICUserValueStructure.Capture_CcrValue+1);

为什么都要加一呢,是因为:

计数器CNT:CNT是16位的计数器,只能往上计数,最大计数值为65535。当计数达到自动重装载寄存器的时候产生更新事件,并清零从头开始计数。

计数器是从0开始计数的,0计数到65536,就是65537个数了。

计算高电平脉宽时间:TIM_PscCLK是计数频率,倒数就是计一个数的周期。

计数器的计数周期 * 高电平时间的计数器的值=(1/TIM_PscCLK) * time=time/TIM_PscCLK。

printf ( "\r\n测得高电平脉宽时间:%d.%d s\r\n",time/TIM_PscCLK,time%TIM_PscCLK );

在这里插入图片描述

#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_usart.h"
#include "bsp_GeneralTim.h"  /*** @brief  主函数* @param  无  * @retval 无*/
int main(void)
{uint32_t time;// TIM 计数器的驱动时钟uint32_t TIM_PscCLK = 72000000 / (GENERAL_TIM_PSC+1);/* 串口初始化 */USART_Config();/* 定时器初始化 */GENERAL_TIM_Init();printf ( "\r\nSTM32 输入捕获实验\r\n" );printf ( "\r\n按下K1,测试K1按下的时间\r\n" );while ( 1 ){if(TIM_ICUserValueStructure.Capture_FinishFlag == 1){// 计算高电平时间的计数器的值time = TIM_ICUserValueStructure.Capture_Period * (GENERAL_TIM_PERIOD+1) + (TIM_ICUserValueStructure.Capture_CcrValue+1);// 打印printf ( "\r\n测得高电平脉宽时间:%d.%d s\r\n",time/TIM_PscCLK,time%TIM_PscCLK );TIM_ICUserValueStructure.Capture_FinishFlag = 0;			}		}
}

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

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

相关文章

stm32 PWM输入捕获

普通的输入捕获,可使用定时器的四个通道,一路捕获占用一个捕获寄存器. PWM输入,只能使用两个通道,通道1和通道2。 一路PWM输入占用两个捕获寄存器,一个捕获周期,一个捕获占空比。 这里,用通用…

直流有刷减速电机结构及其工作原理

寒假无聊拆了个直流有刷减速电机。下面介绍一下它的结构和工作原理 直流电机 直流电机和直流减速电机: 构造上相差的是一个减速齿轮组。 普通的直流电机当空载时,电机的转速由电压决定,直流减速电机的转速由齿轮组和电压决定。 齿轮组作…

数据库基础概念

postgreSQL设置只允许本地机器连接 在D:\program files\PostgreSQL\14\data里面设置postgresql.conf: listen_addresses ‘localhost’ 然后在服务窗口重新启动postgresql。 PostgreSQL执行SQL语句 PostgreSQL的psql工具可通过命令行执行SQL语句。 psql -U po…

电机和驱动的种类

电机种类 直流电机 分为普通的直流电机、直流减速电机、有刷、无刷。 直流有刷减速电机参数: 空载转速,正常工作电压,电机不带任何负载的转速。 空载电流,正常工作电压,电机不带任何负载的工作电流。单位mA。 负载…

Linux shell基础知识

Shell简介 Shell是一个应用程序,接收用户输入的命令,根据命令做出相应动作。 Shell负责将应用层或者用户输入的命令,传递给系统内核。由操作系统内核,来完成相应的工作。然后将结果反馈给应用层或者用户。 shell命令格式&#…

Linux APT VIM 的一些指令

APT APT下载工具,可以实现软件自动下载、配置、安装二进制或源码功能。 APT采用客户端/服务器模式。 sudo apt-get update 更新软件 sudo apt-get check 检查依赖关系 sudo apt-get install package-name 安装软件 apt-get负责下载软件,install负责安…

CATIA 界面介绍

窗口介绍 窗口主要有:菜单栏、工具栏、特征树、罗盘、信息栏、图形区。 菜单栏,开始里面有CATIA的各个功能模块。 图形区,进行3D、2D设计的图形创建、编辑区域。 信息栏,显示用户即将进行操作的文字提示。 工具栏,…

Linux C文件编译

设置编辑器 1.TAB键设置为4空格。 首先用vim打开/etc/vim/vimrc文件,这里面发现root用户才能修改vimrc文件,所以用sudo命令暂时切换到root用户。 在vimrc文件最后面,输入set ts 4完成设置。 然后保存,关闭文件。 2.VIM编辑器显…

catia 草图设计

草图设计界面 进入草图编辑器环境: 菜单栏,文件-新建,然后类型选择Part。 工具栏,点击下面草图按钮。 然后选择草图平面。 然后就进入草图界面。 草图界面主要由菜单栏、工具栏、特征树、信息栏、罗盘、图形区组成。 菜单栏&…

CATIA连接盘实体设计

文件-新建-part。 点击草图按钮,选择xy平面,绘制如下草图。 然后用橡皮擦修改一下。 然后,点击凸台按钮。选择刚刚定义的草图,拉伸20mm。 选择拉伸实体上端面,点击草图按钮,进入草图编辑器。 在草图编辑器…

PostgreSQL 表的创建、删除、更新

psql工具 psql工具,可通过命令行执行SQL语句。 D:\program files\PostgreSQL\14\bin>psql -U postgres 用户 postgres 的口令: psql (14.2) 输入 "help" 来获取帮助信息.postgres#创建数据库 创建表之前,先创建存储表的数据库…

PostgreSQL 简单的查询

查询列 SELECT语句&#xff0c;用于从表中选取数据。 格式&#xff1a; SELECT <列名>,... FROM <表名>;从Product表中&#xff0c;查询三列。 SELECT product_id, product_name, purchase_price FROM Product;查询所有列&#xff0c;格式&#xff1a; SELECT …

PostgreSQL 聚合、分组、排序

聚合函数 用于汇总的函数。 COUNT COUNT&#xff0c;计算表中的行数(记录数)。 计算全部数据的行数&#xff1a; SELECT COUNT(*)FROM Product;NULL之外的数据行数&#xff1a; SELECT COUNT(purchase_price)FROM Product;结果如下图。 对于一个含NULL的表&#xff1a; …

PostgreSQL 插入、删除、更新、事务

INSERT 使用INSERT语句可以向表中插入数据。 创建一个表&#xff1a; CREATE TABLE ProductIns (product_id CHAR(4) NOT NULL,product_name VARCHAR(100) NOT NULL,product_type VARCHAR(32) NOT NULL,sale_price INTEGER DEFAULT 0,purchase_p…

PostgreSQL 视图、子查询

视图 表里面保存的是实际数据&#xff0c;视图里面保存的是SELECT语句(视图本身不存储数据)。 从视图中读取数据&#xff0c;此时视图在内部执行SELECT语句&#xff0c;创建一张临时表。 使用视图的好处&#xff1a;其一&#xff0c;视图不保存数据&#xff0c;节省存储设备…

GD32F307 DAC 输出波形

文章目录DACDAC_CTL 控制寄存器定时器TIMERx_CTL1 控制寄存器改变波形频率DMADMA和外设配合DMA_CHxCNT计数寄存器波形曲线总结源码DAC 如下面框图所示&#xff0c;使能外部触发后&#xff08;通过设置 DAC_CTL 寄存器的 DTENx 位&#xff09;&#xff0c; 当已经选择的触发事件…

GD32 ADC采集电压

文章目录ADCTIMDMA其他一些初始化main总结使用芯片为GD32F307 ADC 连续转换模式&#xff0c;可以运行在规则组通道上&#xff0c;一旦相应软件触发或者外部触发产生&#xff0c;ADC就会采样和转换规定的通道。 采样时间&#xff0c;每个通道可以用不同的时间采样。ADC使用若…

DAC、ADC、FFT使用总结

目录计算公式波形生成DAC波形频率ADC采样时间离散傅里叶变换DFTFFT计算公式 DAC、ADC、FFT之间有些参数环环相扣&#xff0c;所以先整合一下公式。 1.系统时钟周期72MHZ。 2.定时器的单个时钟周期。 3.定时器的触发周期。 4.正弦波一个周期的时间&#xff0c;其中N为正弦波一…

c++代码根据点位连线_邹军:数控车倒角C与自动倒圆角R编程方法

提示&#xff1a;点击上方↑↑"数控达人"即可每天免费订阅【邹军&#xff0c;十多年数控工作经验&#xff0c;现自创一套有理论&#xff0c;有干货&#xff0c;还有方法论做支撑的实战编程教程(PDF)&#xff0c;从而让你编写程序就像做填空题一样简单。在没有人指引你…

不愿意和别人打交道_始终和人保持距离,最不合群的3星座,孤僻却有真本事,能成大事...

始终和人保持距离&#xff0c;最不合群的3星座&#xff0c;孤僻却有真本事&#xff0c;能成大事巨蟹座巨蟹座的人真的是天生孤僻&#xff0c;他们始终和人保持距离&#xff0c;也不喜欢跟别人打交道&#xff0c;最怕就是应酬的事&#xff0c;看起来很不合群&#xff0c;但是巨蟹…