【4】STM32·FreeRTOS·中断管理

目录

一、什么是中断

二、中断优先级分组设置

2.1、中断优先级基本概念

2.2、中断优先级分组

2.3、FreeRTOS中断特点

三、中断相关寄存器

3.1、系统中断优先级配置寄存器

3.2、PendSV和Systick中断优先级的配置

3.3、中断屏蔽寄存器

四、FreeRTOS中断管理实验


一、什么是中断

 让 CPU 打断正常运行的程序,转而去处理紧急的事件(程序),就叫中断

中断执行机制,可简单概括为三步

1、中断请求:外设产生中断请求(GPIO外部中断、定时器中断等)

2、响应中断:CPU 停止执行当前程序,转而去执行中断处理程序(ISR)

3、退出中断:执行完毕,返回被打断的程序处,继续往下执行

二、中断优先级分组设置

2.1、中断优先级基本概念

ARM Cortex-M 使用了 8 位宽的寄存器来配置中断的优先等级,这个寄存器就是中断优先级配置寄存器,但 STM32,只用了中断优先级配置寄存器的高 4 位 [7:4],所以 STM32 提供了最大16级的中断优先级

STM32 的中断优先级可以分为抢占优先级和子优先级

抢占优先级:高抢占优先级可以打断正在执行的低抢占优先级中断

子优先级:当抢占优先级相同时,子优先级高的先执行,但是不能互相打断

注意:中断优先级数值越小越优先

2.2、中断优先级分组

一共有 5 种分配方式,对应着中断优先级分组的 5 个组

优先级分组抢占优先级子优先级优先级配置寄存器高 4 位
NVIC_PRIORITYGROUP_00 级抢占优先级0-15 级子优先级

0bit 用于抢占优先级

4bit 用于子优先级

NVIC_PRIORITYGROUP_10-1 级抢占优先级0-7 级子优先级

1bit 用于抢占优先级

3bit 用于子优先级

NVIC_PRIORITYGROUP_20-3 级抢占优先级0-3 级子优先级

2bit 用于抢占优先级

2bit 用于子优先级

NVIC_PRIORITYGROUP_30-7 级抢占优先级0-1 级子优先级

3bit 用于抢占优先级

1bit 用于子优先级

NVIC_PRIORITYGROUP_40-15 级抢占优先级0 级子优先级

4bit 用于抢占优先级

0bit 用于子优先级

在 FreeRTOS 中使用的是 NVIC_PRIORITYGROUP_4,任何其他配置都会使 configMAX_SYSCALL_INTERRUPT_PRIORITY 设置与分配给各个外设中断的优先级之间的直接关系复杂化

在 HAL_Init 中,通过调用函数 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4) 即可完成设置

2.3、FreeRTOS中断特点

1、低于 configMAX_SYSCALL_INTERRUPT_PRIORITY 优先级的中断里才允许调用 FreeRTOS 的 API 函数

2、建议将所有优先级位指定为抢占优先级位,方便 FreeRTOS 管理(调用函数 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4) )

3、中断优先级数值越小越优先,任务优先级数值越大越优先

三、中断相关寄存器

3.1、系统中断优先级配置寄存器

三个系统中断优先级配置寄存器,分别为 SHPR1、SHPR2、SHPR3

SHPR1 寄存器地址:0xE000ED18

SHPR2 寄存器地址:0xE000ED1C

SHPR3 寄存器地址:0xE000ED20

3.2、PendSV和Systick中断优先级的配置

在 xPortStartScheduler() 函数中,将 PendSV 和 SysTick 设置为优先级最低的中断,这个函数在 vTaskStartScheduler() 开启任务调度函数中会调用

/* Make PendSV and SysTick the lowest priority interrupts. */portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;

SHPR3 寄存器地址的定义

#define portNVIC_SHPR3_REG    ( *( ( volatile uint32_t * ) 0xe000ed20 ) )

PendSV 和 SysTick 优先级配置寄存器相对 SHPR3 寄存器的偏移

#define portNVIC_PENDSV_PRI     ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI    ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )

将设置的中断最低优先级左移 4 位作为中断优先级配置寄存器的高 4 位 [7:4] 进行赋值

/* 中断嵌套行为配置 */
#ifdef __NVIC_PRIO_BITS#define configPRIO_BITS __NVIC_PRIO_BITS
#else#define configPRIO_BITS 4
#endif#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY         15                  /* 中断最低优先级 */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    5                   /* FreeRTOS可管理的最高中断优先级 */
#define configKERNEL_INTERRUPT_PRIORITY                 ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

偏移 4 的定义

#define __NVIC_PRIO_BITS          4        /*!< STM32F4XX uses 4 Bits for the Priority Levels */

所以:PendSV 和 SysTick 设置为最低优先级

设置最低:保证系统任务切换不会阻塞系统其他中断的响应

3.3、中断屏蔽寄存器

三个中断屏蔽寄存器,分别为 PRIMASK、FAULTMASK、BASEPRI

FreeRTOS 所使用的中断管理就是利用的 BASEPRI 这个寄存器

BASEPRI:屏蔽优先级低于某一个阈值的中断,当设置为 0 时,则不关闭任何中断

比如:BASEPRI 设置为 0x50,代表中断优先级在 5~15 内的均被屏蔽,0~4 的中断优先级正常执行

关中断程序示例(中断优先级在 5~15 的全部被关闭)

#define portDISABLE_INTERRUPTS()                  vPortRaiseBASEPRI()static portFORCE_INLINE void vPortRaiseBASEPRI( void )
{uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;__asm{/* Set BASEPRI to the max syscall priority to effect a critical* section. */
/* *INDENT-OFF* */msr basepri, ulNewBASEPRIdsbisb
/* *INDENT-ON* */}
}#define configMAX_SYSCALL_INTERRUPT_PRIORITY            ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    5                   /* FreeRTOS可管理的最高中断优先级 */

当 BASEPRI 设置为 0x50 时

在中断服务函数中调度 FreeRTOS 的 API 函数需注意

1、中断服务函数的优先级需在 FreeRTOS 所管理的范围内

2、在中断服务函数里边需调用 FreeRTOS 的 API 函数,必须使用带“FromISR”后缀的函数

开中断程序示例

#define portENABLE_INTERRUPTS()                   vPortSetBASEPRI( 0 )static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI )
{__asm{/* Barrier instructions are not used as this function is only used to* lower the BASEPRI value. */
/* *INDENT-OFF* */msr basepri, ulBASEPRI
/* *INDENT-ON* */}
}

FreeRTOS 中断管理就是利用 BASEPRI 寄存器实现的

四、FreeRTOS中断管理实验

本实验会使用两个定时器每 1s 分别打印一段字符串,一个优先级为 4,一个优先级为 6,注意:系统所管理的优先级范围:5~15

将设计两个任务:start_task、task1

两个任务的功能如下

start_task:用来创建 task1 任务

task1:中断测试任务,任务中将调用关中断和开中断函数来体现对中断的管理作用

main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "freertos_demo.h"int main(void)
{HAL_Init();                         /* 初始化HAL库 */sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */delay_init(168);                    /* 延时初始化 */usart_init(115200);                 /* 串口初始化为115200 */led_init();                         /* 初始化LED */lcd_init();                         /* 初始化LCD */key_init();                         /* 初始化按键 */freertos_demo();
}

freertos_demo.c

#include "freertos_demo.h"/******************************************************************************************************/
/*FreeRTOS配置*//* START_TASK 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define START_TASK_PRIO 1            /* 任务优先级 */
#define START_STK_SIZE 128           /* 任务堆栈大小 */
TaskHandle_t StartTask_Handler;      /* 任务句柄 */
void start_task(void *pvParameters); /* 任务函数 *//* TASK1 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK1_PRIO 2            /* 任务优先级 */
#define TASK1_STK_SIZE 128      /* 任务堆栈大小 */
TaskHandle_t Task1Task_Handler; /* 任务句柄 */
void task1(void *pvParameters); /* 任务函数 *//******************************************************************************************************//* FreeRTOS例程入口函数 */
void freertos_demo(void)
{lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);lcd_show_string(10, 47, 220, 24, 24, "Interrupt", RED);lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);xTaskCreate((TaskFunction_t)start_task,          /* 任务函数 */(const char *)"start_task",          /* 任务名称 */(uint16_t)START_STK_SIZE,            /* 任务堆栈大小 */(void *)NULL,                        /* 传入给任务函数的参数 */(UBaseType_t)START_TASK_PRIO,        /* 任务优先级 */(TaskHandle_t *)&StartTask_Handler); /* 任务句柄 */vTaskStartScheduler();
}/* start_task */
void start_task(void *pvParameters)
{taskENTER_CRITICAL(); /* 进入临界区 *//* 初始化TIM3、TIM5 */btim_tim3_int_init(10000 - 1, 8400 - 1);btim_tim5_int_init(10000 - 1, 8400 - 1);/* 创建任务1 */xTaskCreate((TaskFunction_t)task1,               /* 任务函数 */(const char *)"task1",               /* 任务名称 */(uint16_t)TASK1_STK_SIZE,            /* 任务堆栈大小 */(void *)NULL,                        /* 传入给任务函数的参数 */(UBaseType_t)TASK1_PRIO,             /* 任务优先级 */(TaskHandle_t *)&Task1Task_Handler); /* 任务句柄 */vTaskDelete(StartTask_Handler); /* 删除开始任务 */taskEXIT_CRITICAL();            /* 退出临界区 */
}/* task1 */
void task1(void *pvParameters)
{uint32_t task1_num = 0;while (1){if (++task1_num == 5){printf("FreeRTOS Close Interrupt\r\n");portDISABLE_INTERRUPTS(); /* FreeRTOS关闭中断 */delay_ms(5000);           /* 不能使用vTaskDelay,vTaskDelay内部会执行开中断操作 */printf("FreeRTOS Open Interrupt\r\n");portENABLE_INTERRUPTS(); /* FreeRTOS打开中断 */task1_num = 0;}vTaskDelay(1000);}
}

freertos_demo.h

#ifndef __FREERTOS_DEMO_H
#define __FREERTOS_DEMO_H#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/TIMER/btim.h"
#include "FreeRTOS.h"
#include "task.h"void freertos_demo(void);#endif

btim.c

#include "./BSP/TIMER/btim.h"TIM_HandleTypeDef g_tim3_handle; /* 定时器3句柄 */
TIM_HandleTypeDef g_tim5_handle; /* 定时器5句柄 *//* 基本定时器TIM3中断服务函数 */
void BTIM_TIM3_INT_IRQHandler(void)
{HAL_TIM_IRQHandler(&g_tim3_handle); /*定时器回调函数*/
}/* 基本定时器TIM5中断服务函数 */
void BTIM_TIM5_INT_IRQHandler(void)
{HAL_TIM_IRQHandler(&g_tim5_handle); /*定时器回调函数*/
}/* 回调函数,定时器中断服务函数调用 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if (htim == (&g_tim3_handle)){printf("TIM3 Output\r\n");}else if (htim == (&g_tim5_handle)){printf("TIM5 Output\r\n");}
}/*  基本定时器TIM3定时中断初始化函数 */
void btim_tim3_int_init(uint16_t arr, uint16_t psc)
{g_tim3_handle.Instance = BTIM_TIM3_INT;                    /*通用定时器3*/g_tim3_handle.Init.Prescaler = psc;                        /* 设置预分频器  */g_tim3_handle.Init.CounterMode = TIM_COUNTERMODE_UP;       /* 向上计数器 */g_tim3_handle.Init.Period = arr;                           /*自动装载值*/g_tim3_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; /*时钟分频因子*/HAL_TIM_Base_Init(&g_tim3_handle);HAL_TIM_Base_Start_IT(&g_tim3_handle); /*使能通用定时器3和及其更新中断:TIM_IT_UPDATE*/
}/*  基本定时器TIM5定时中断初始化函数 */
void btim_tim5_int_init(uint16_t arr, uint16_t psc)
{g_tim5_handle.Instance = BTIM_TIM5_INT;                    /*通用定时器5*/g_tim5_handle.Init.Prescaler = psc;                        /* 设置预分频器  */g_tim5_handle.Init.CounterMode = TIM_COUNTERMODE_UP;       /* 向上计数器 */g_tim5_handle.Init.Period = arr;                           /*自动装载值*/g_tim5_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; /*时钟分频因子*/HAL_TIM_Base_Init(&g_tim5_handle);HAL_TIM_Base_Start_IT(&g_tim5_handle); /*使能通用定时器5和及其更新中断:TIM_IT_UPDATE*/
}/* 定时器底层驱动,开启时钟,设置中断优先级 */
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{if (htim->Instance == BTIM_TIM3_INT){BTIM_TIM3_INT_CLK_ENABLE();                     /*使能TIM时钟*/HAL_NVIC_SetPriority(BTIM_TIM3_INT_IRQn, 4, 0); /* 抢占4,子优先级0,组4 */HAL_NVIC_EnableIRQ(BTIM_TIM3_INT_IRQn);         /*开启ITM3中断*/}else if (htim->Instance == BTIM_TIM5_INT){BTIM_TIM5_INT_CLK_ENABLE();                     /*使能TIM时钟*/HAL_NVIC_SetPriority(BTIM_TIM5_INT_IRQn, 6, 0); /* 抢占6,子优先级0,组4 */HAL_NVIC_EnableIRQ(BTIM_TIM5_INT_IRQn);         /*开启ITM5中断*/}
}

bitm.h

#ifndef _BTIM_H
#define _BTIM_H#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/USART/usart.h"
#include "./BSP/LED/led.h"/******************************************************************************************/
/* 基本定时器 定义 *//* TIMX 中断定义 * 默认是针对TIM6/TIM7* 注意: 通过修改这4个宏定义,可以支持TIM1~TIM8任意一个定时器.*/#define BTIM_TIM3_INT                       TIM3
#define BTIM_TIM3_INT_IRQn                  TIM3_IRQn
#define BTIM_TIM3_INT_IRQHandler            TIM3_IRQHandler
#define BTIM_TIM3_INT_CLK_ENABLE()          do{ __HAL_RCC_TIM3_CLK_ENABLE(); }while(0)  /* TIM3 时钟使能 */#define BTIM_TIM5_INT                       TIM5
#define BTIM_TIM5_INT_IRQn                  TIM5_IRQn
#define BTIM_TIM5_INT_IRQHandler            TIM5_IRQHandler
#define BTIM_TIM5_INT_CLK_ENABLE()          do{ __HAL_RCC_TIM5_CLK_ENABLE(); }while(0)  /* TIM5 时钟使能 *//******************************************************************************************/void btim_tim3_int_init(uint16_t arr, uint16_t psc);
void btim_tim5_int_init(uint16_t arr, uint16_t psc);#endif

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

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

相关文章

阿里云服务器在线安装nginx

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《nginx实战》 目录 内容简介 安装步骤 1.root用户登录连接阿里云服务器 2.在usr/local下新建nginx目录 3.安装 1安装下载工具 2下载nginx压缩包 3解压 4安装nginx依赖的库 5编译并安装 6启动nginx 7开启…

ShellCode详解三

直接进入正题。 在完成正式的shellcode代码导出之前&#xff0c;我们先手动的对代码进行导出&#xff0c;以使各位同学更加了解其原理。 手动注入shellcode 1、我们利用DLE工具找到上一节中我们生成的PE文件的代码段位置 上述图片就是我们的代码段位置 2、利用WinHex工具我…

Appium测试之获取appPackage和appActivity

appPackage和appActivity 进行appium自动化测试非常重要的两个参数&#xff0c;我们所测试的APP不同&#xff0c;这两个参数肯定也是不一样的。那如何快速的获取这APP的这两个参数呢&#xff1f;我这里介绍两个方法。 import org.openqa.selenium.remote.DesiredCapabilities;i…

韩国站群服务器在全球网络架构中的重要作用?

韩国站群服务器在全球网络架构中的重要作用? 在全球互联网的蓬勃发展中&#xff0c;站群服务器作为网络架构的核心组成部分之一&#xff0c;扮演着至关重要的角色。韩国站群服务器以其卓越的技术实力、优越的地理位置、稳定的网络基础设施和强大的安全保障能力&#xff0c;成…

docker(二):Centos安装docker

文章目录 1、安装docker2、启动docker3、验证 官方文档&#xff1a;https://docs.docker.com/engine/install/centos/ 1、安装docker 下载依赖包 yum -y install gcc yum -y install gcc-c yum install -y yum-utils设置仓库 yum-config-manager --add-repo http://mirrors…

端到端将重塑智驾?获10亿美金融资,解密英国AI独角兽Wayve

‍作者 |张马也 编辑 |德新 就在前两天&#xff0c;英国AI公司Wayve宣布获得新一轮10.5亿美元融资&#xff0c;投资方为软银、英伟达和现有投资人微软&#xff0c;可以说是顶级豪华阵容。 作为一家英国公司&#xff0c;Wayve这轮融资也创造了英国AI公司有史以来最大的单笔融资…

北斗卫星在农田测量中的广泛应用

北斗卫星在农田测量中的广泛应用 随着科技的不断发展和进步&#xff0c;北斗卫星在农田测量中的应用也越来越广泛。北斗卫星系统是我国自行研制的卫星导航定位系统&#xff0c;具有全球覆盖、高精度和高可靠性的特点&#xff0c;是农田测量领域不可或缺的重要工具。 首先&…

Laravel框架使用图片处理简单教程

PHP图片处理扩展包使用 文中使用的是Laravel框架&#xff0c;更多框架扩展包请点击传送门-》更多框架集成 Intervention Image 是一个开源的 PHP 图像处理和操作 库。它提供了一个更简单也更优雅的方式来创建/编辑/组合图像,并且支持最常见的两个图像处理库 GD Library 和 Im…

静态分析-RIPS-源码解析记录-01

token流扫描重构部分&#xff0c;这一部分主要利用php的token解析api解析出来的token流&#xff0c;对其中的特定token进行删除、替换、对于特定的语法结构进行重构&#xff0c;保持php语法结构上的一致性 解析主要在lib/scanner.php中通过Tokenizer这个类来实现,也就是在main…

机器学习面试篇

如何理解机器学习数据集的概念 数据集是机器学习的基础&#xff0c;它包括了用于训练和测试模型所需的数据。数据集通常以矩阵的形式存在&#xff0c;其中每一行代表一个样本&#xff08;或实例&#xff09;&#xff0c;每一列代表一个特征&#xff08;或属性&#xff09;。…

SpringAMQP Work Queue 工作队列

消息模型: 代码模拟: 相较于之前的基础队列&#xff0c;该队列新增了消费者 不再是一个&#xff0c;所以我们通过代码模拟出两个consumer消费者。在原来的消费者类里写两个方法 其中消费者1效率高 消费者2效率低 RabbitListener(queues "simple.queue")public voi…

学习网络需要认识的各种设备

网桥&#xff08;bridge&#xff09; 网桥工作在数据链路层&#xff0c;可以把多个局域网连接起来&#xff0c;组成一个更大的局域网 以太网中&#xff0c;数据链路层地址就是mac地址&#xff0c;网桥与集线器的区别就是&#xff0c;网桥会过滤mac&#xff0c;只有目的mac地址…

draw.io 网页版二次开发(2):开始修改代码

目录 一 说明 二 打开开发环境 1. 代码调整 2. 修改访问链接 3. 注意 三 部分功能的代码汇总 1. 保存功能 2. 菜单栏折叠按钮功能 3. 顶部菜单栏 4.在顶部菜单栏中的【文件】菜单中新增选项 &#xff08;1&#xff09; 方法一&#xff1a;单独增加 &#xff08;…

calllback回调函数:同步调用,异步调用,异步回调

纯python代码的异步回调 # _*_ encoding:utf-8 _*_ import time import threading callback_value None onFlag Truedef add(a, b, num):print(f"I am the function: %s, please wait for %d" % (add.__name__, num))time.sleep(num)c a bprint("a b 1 &…

K8S搭建

文章目录 K8S搭建配置要求 安装 Kuboard-Spray加载离线资源包规划并安装集群访问集群重启Kubernetes集群Worker节点不能启动许多Pod一直Crash或不能正常访问 containerd配置网络代理 常用的 kubectl 命令&#xff1a; K8S搭建 安装高可用的Kubernetes集群 配置要求 对于 Kub…

Springboot+mybatis-plus+dynamic-datasource+继承DynamicRoutingDataSource切换数据源

Springbootmybatis-plusdynamic-datasource继承DynamicRoutingDataSource切换数据源 背景 最近公司要求支持saas&#xff0c;实现动态切换库的操作&#xff0c;默认会加载主租户的数据源&#xff0c;其他租户数据源在使用过程中自动创建加入。 解决问题 1.通过请求中设置租…

软件产品检测认证是什么?

软件产品检测认证是软件企业、系统集成商或软件商为了提高自身产品的竞争力&#xff0c;增强客户信心&#xff0c;通过第三方机构对企业的软件产品质量和可靠性进行全面测试与评估的过程。这一过程主要关注软件产品的功能、性能、安全性、可维护性等方面&#xff0c;确保软件产…

FileLink跨网文件传输医疗行业解决方案

随着医疗行业的快速发展&#xff0c;医疗机构之间的信息共享和文件传输需求日益增加。然而&#xff0c;由于网络环境的复杂性和数据安全性的要求&#xff0c;传统的文件传输方式已经无法满足医疗行业的需求。为此&#xff0c;我们推出了FileLink跨网文件传输医疗行业解决方案&a…

炫酷个人主页(源码免费)

炫酷个人主页 效果图部分代码领取源码下期更新预报 效果图 部分代码 <!DOCTYPE html> <!--哪怕是深爱之人 对我们的痛苦一无所知&#xff01;* ░░░░░░░░░░░░░░░░░░░░░░░░▄░░* ░░░░░░░░░▐█░░░░░░░░░░░▄▀▒▌░* ░…

智能座舱语音助手产品方案

一、用户调研与痛点分析 1.目标用户分析 用户画像 性别女性年龄50地域2-3线城市职业退休或退居二线教育中专、 大专、 本科财务家庭财务管理者爱好享受生活、 照顾家庭标签有闲有小钱二、产品定位与卖点提炼 购车目的 愉悦自我&#xff0c; 专属于自己的座驾&#xff1a; 家…