
「2019 Python开发者日」,购票请扫码咨询 ↑↑↑
作者 | 琥珀
出品 | AI科技大本营(ID:rgznai100)
在无人驾驶领域,自动驾驶级别和量产一直是所关注的两大焦点,前者关乎技术实力,后者直接决定着项目的商业落地能力。尤其对于特斯拉,其一举一动都会影响它在投资者心中的想象空间。
现实情况却是,这样的日子愈发变得糟糕。
近日,特斯拉发布了 2019 年第一季度产能 & 交付公告。
特斯拉 2019 Q1 生产 77100 辆汽车,包括 62950 辆 Model 3 和 14150 辆 Model S/X;共交付 63000 辆汽车,包括 50900 辆 Model 3 和 12100 辆 Model S/X。
特斯拉在公告中指出,此次交付的 63000 辆汽车,较去年同期增长 110%,但较上季度下降 31%。(此前,特斯拉曾公开表示,预计 Q1 交付量将高于 2018 Q4 的 90966 辆汽车。)这其中包括交付量为 5.09 万辆的 Model 3 和 1.21 万辆的 Model S 和 Model X。
尽管特斯拉给出的解释是:特斯拉在欧洲及中国市场交付量暴增,有时甚至超过此前峰值交付量的 5 倍,影响交付的不是 “需求” 问题,而是其他因素,但显然,市场投资者对这样的说法并不满意。当天,特斯拉股价应声下跌 8%,创下 267.27 美元的成交价。
要知道,在 3 月 14 日的 Model Y 新品发布会上,其 CEO 埃隆 · 马斯克还特地指出,从现在开始 1 年后,特斯拉会交付100万台,目前已经交付 50 多万量电动车,刚刚过半。
这意味着什么?
如果按照这个数字估算的话,暂不考虑可能存在的产能爬坡,我们可以得到:特斯拉未来一年平均每季度将交付 12.5 万辆汽车。
马斯克曾说,2018 年特斯拉的 “每个员工” 每周工作 100 个小时,相当于平均每天工作 14 个小时。这样来看,接下来特斯拉员工将面临更为巨大的加班“挑战”!
当然,除了频频跳票的 Model 3,还有打了折也收效不佳的 Model S 和 Model X。
卖不出去的 Model S/X
中国市场,无疑是特斯拉提振市场信心的途径之一。
在此前的财报前瞻指引中,特斯拉曾预警美国于 2019 年 1 月 1 日实施的纯电动车补贴退坡的问题。在北美地区,补贴退坡对特斯拉汽车销量产生了巨大影响。这样的大背景下,尤其是对于需求不足的 Model S 和 Model X 亟需拓展新的市场。这也是去一段时间,特斯拉在中国市场频繁调价的结果,其官方降价幅度为 15%-40% 不等。不过,该行为引发了很多已购车主的强烈不满。
据了解,除了在内华达州的超级工厂(Gigafactory)之外,特斯拉在中国上海的超级工厂也建设迅速,其规模是相比现有超级工厂的两倍。同样,该车厂将会负责 Model 3 和 Model Y 的生产。尽管特斯拉在华生产并不等于国产车,但 “它也不再属于美国贸易品了,所以不必按照 40% 的关税交钱,但会以标准进口车 15% 的关税来计算。” 田忠朝写道。
实际结果却是,特斯拉 Model S 和 Model X 在中国市场的情况不容乐观。
42 号车库写道,
“在销量如此不及预期的情况下,特斯拉在公告中重申了全年 36 万辆 - 40 万辆的销量指引。这意味着 Model S/X 全年 10 万辆的销量指引维持不变,在接下来的三个季度,Model S/X 的平均季度销量要达到 2.93 万辆。在特斯拉的历史上,这样的销量成绩从未出现。”
如此激进式低价促销的一个重要原因是特斯拉需要稳定的现金流,未来几年里,特斯拉将有可能继续降低车辆售价,进而提高市场占有率。
在这个过程中,产品的质量环节又该如何保证呢?
2016 年 5 月,特斯拉 Model S 在美国佛罗里达州发生首例自动驾驶致死事故。
2018 年 2 月 27 日,河北省一名特斯拉车主开启 Autopilot 自动驾驶模式后发生事故殒命。
2018 年 3 月份,在加州山景城附近的高速公路上,特斯拉 Model X 车主开启了自动驾驶功能,车子撞上中间隔离栏后汽车发生起火,之后又被车道后方驶来的一辆马自达和一辆奥迪相继撞上。特斯拉的司机被送到医院后因伤重不治而死亡。
2018 年 5 月, 在美国加州 Laguna Beach 市,一辆开启自动驾驶 Autopilot 功能的特斯拉 Model S 撞上一辆停靠在路边的警车。
结语
在特斯拉之前,没有一辆电动车能取得如此风光的成就。早在 2003 年起,特斯拉就开始生产汽车,直到 2008 年推出第一款车,2015 年,特斯拉率先推出带有 L2 级自动驾驶功能的 Autopilot,引发了业界强烈关注。
不得不承认,此前在价格、体验、技术性能等方面的优势促成了特斯拉如今的地位,特斯拉很长一段时间里也引领着行业发展,短期来看,为了维持产能采取激进的方式也无可厚非,那么长期来看呢?
(本文为 AI大本营原创文章,转载请微信联系 1092722531)
◆
精彩推荐
◆
「2019 Python开发者日」演讲议题全揭晓!这一次我们依然“只讲技术,拒绝空谈”10余位一线Python技术专家共同打造一场硬核技术大会。更有深度培训实操环节,为开发者们带来更多深度实战机会。更多详细信息请咨询13581782348(微信同号)。
推荐阅读:
❤点击“阅读原文”,查看历史精彩文章。
第六章:freertosconfig.h核心函数详解(官方最新版,附FreeRTOSconfig.h归类完的完整中文注释)
STM32上创建简单FreeRTOS程序详解
前言
本文将详细讲解如何在STM32平台上创建一个简单的FreeRTOS程序,并通过一个LED闪烁任务来验证程序的正确运行。整个过程将按照步骤一步一步展开,确保即使是初学者也能轻松上手。
源码获取:本教程相关的工程文件已上传至GitHub,您可以通过以下链接获取完整代码:
https://github.com/Despacito0o/FreeRTOS.git
开发环境准备
- Keil MDK 5.42a 或更高版本
- STM32F103系列开发板(本教程使用STM32F103C8)
- ST-Link调试器(如使用实际硬件)
具体步骤
1. 复制工程模板
首先,我们需要复制之前创建好的工程模板,并命名为003。这样做是为了保留原始工程,同时在新的工程上进行FreeRTOS程序的开发,避免对原有工程造成破坏。使用模板也能确保基础的STM32配置已经完成,省去了从零开始的繁琐步骤。
提示:如果您直接从GitHub克隆了项目,可以在
Despacito/002
目录中找到基础工程模板。
2. 清理不必要的头文件
打开工程文件,删除不需要的头文件。这一步是为了精简工程,删除与我们当前FreeRTOS程序开发无关的组件,减少可能的冲突和编译错误。同时,一个干净的工程结构也有助于我们更清晰地理解FreeRTOS的组成部分和我们的程序结构。
3. 修改FreeRTOS配置文件
接下来,我们需要修改freertosconfig.h
文件,添加三个关键中断处理函数的定义。这是FreeRTOS程序开发中的重要一步。FreeRTOS需要使用系统的一些中断处理,包括:
- PendSV_Handler:用于任务切换
- SVC_Handler:用于系统服务调用
- SysTick_Handler:用于系统滴答计时,是FreeRTOS进行任务调度的时间基准
通过这样的定义,我们告诉编译器FreeRTOS的中断处理函数将使用系统默认的同名函数。
#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler
#define xPortSysTickHandler SysTick_Handler
- 1
- 2
- 3
4. 注释原有中断处理函数
由于上一步中我们已经将三个关键中断交给了FreeRTOS处理,所以需要在STM32的中断文件stm32f10x_it.c
中注释掉原本的这三个中断处理函数。如果不注释,将会导致函数重定义错误,因为FreeRTOS和STM32标准库都定义了相同名称的函数。
5. 编写测试程序
完成基础配置后,我们需要编写一个测试程序来验证FreeRTOS是否正常工作。在嵌入式系统开发中,LED闪烁通常是最简单且直观的测试方式,也被称为"嵌入式世界的Hello World"。
5.1 定义任务句柄
首先定义一个任务句柄,它是FreeRTOS中用于操作和管理任务的标识符。
TaskHandle_t myTaskHandler;
- 1
5.2 创建任务
使用xTaskCreate
函数创建一个任务,这个函数有六个参数:
- 任务函数名称:
myTask
,指定任务的入口函数 - 任务名称:
"myTask"
,一个字符串,用于调试识别 - 堆栈大小:
128
,指定任务所需的堆栈空间大小 - 传入参数:
NULL
,可以传递给任务的参数 - 优先级:
2
,任务优先级,数字越大优先级越高 - 任务句柄:
&myTaskHandler
,用于返回任务的句柄
xTaskCreate(myTask, "myTask", 128, NULL, 2, &myTaskHandler);
- 1
5.3 启动任务调度器
创建任务后,需要启动FreeRTOS的任务调度器,使系统开始运行并根据任务优先级进行调度。
vTaskStartScheduler();
- 1
5.4 创建任务函数
定义任务函数,这是任务执行的入口。FreeRTOS任务函数通常是一个无限循环,因为任务终止会导致系统出错。
void myTask(void *arg)
{
while(1)
{
// 任务代码将在这里执行
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
5.5 实现LED闪烁功能
在任务函数中添加LED翻转操作,使LED以固定时间间隔闪烁,这样我们可以直观地观察任务是否正常执行。
void myTask(void *arg)
{
while(1)
{
GPIO_ResetBits(GPIOC, GPIO_Pin_13); // LED亮
vTaskDelay(500); // 延时500个时钟节拍,相当于500ms
GPIO_SetBits(GPIOC, GPIO_Pin_13); // LED灭
vTaskDelay(500); // 再延时500ms
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
这里的vTaskDelay
函数是FreeRTOS提供的延时函数,它会使当前任务进入阻塞状态,并允许其他任务运行,实现了真正的多任务操作。
代码说明:与传统的延时函数不同,
vTaskDelay
不会占用CPU资源。当任务调用此函数后,FreeRTOS会将该任务置于阻塞状态,并切换到其他就绪任务执行,直到指定的延时时间到达。
6. 配置调试环境
为了验证我们的程序,需要正确配置调试环境。点击IDE中的"魔法棒"(Debug按钮),选择"use Simulator",并设置适合STM32F103C8芯片的调试参数:
- Dialog DLL:DARMSTM.DLL
- Parameter:-PSTM32F103C8
这些设置告诉调试器使用STM32设备模拟器,并指定了正确的芯片型号,确保仿真环境与实际硬件一致。
7. 开始调试
配置完成后,点击调试按钮开始调试过程。此时,调试器会加载程序到虚拟的STM32芯片中,并准备执行。
8. 打开逻辑分析仪
为了直观地观察LED的状态变化,我们需要打开IDE中的逻辑分析仪工具。逻辑分析仪可以实时显示GPIO引脚状态的变化,帮助我们确认任务是否按预期执行。
9. 配置逻辑分析仪
点击逻辑分析仪左上角的"Setup…"按钮,开始配置要监视的引脚。
10. 添加监视变量
在弹出的配置窗口中,添加要监视的GPIO引脚。在本例中,我们使用的是PC13引脚(GPIOC的第13号引脚),这通常是STM32F103C8板载LED的控制引脚。输入"portc.13"后点击空白处确认添加。
12. 设置显示类型
继续点击刚刚添加的变量(PC13),将显示类型(Display Type)改为"bit",这样可以更清晰地看到引脚的高低电平变化。完成设置后点击"Close"关闭配置窗口。
13. 运行程序
配置完成后,点击"Run"按钮开始运行程序。此时,FreeRTOS调度器会启动,并开始执行我们创建的LED闪烁任务。
14. 观察结果
如果一切正常,我们应该能在逻辑分析仪中观察到PC13引脚的电平状态按照500ms的间隔周期性变化,这表明我们的FreeRTOS任务已经成功创建并正常执行。这也证明了我们的简单FreeRTOS程序已经成功运行。
常见问题与解决方案
1. 编译报错:函数重定义
问题:编译时出现PendSV_Handler、SVC_Handler或SysTick_Handler函数重定义错误。
解决方案:检查是否正确注释了stm32f10x_it.c
中的对应函数。
2. LED不闪烁
问题:程序运行后,LED没有按预期闪烁。
解决方案:
- 检查GPIO配置是否正确
- 确认延时时间是否合适
- 检查任务是否成功创建(可以使用任务状态查看函数)
3. 堆栈溢出
问题:运行时出现堆栈溢出错误。
解决方案:增加任务堆栈大小,修改xTaskCreate
中的堆栈参数(第三个参数)。
本节课main.c代码
#include "stm32f10x.h" // Device header
#include "FreeRTOS.h"
#include "task.h"
TaskHandle_t myTaskHandler;
void myTask(void *arg)
{
while(1)
{
GPIO_ResetBits(GPIOC, GPIO_Pin_13);
vTaskDelay(500);
GPIO_SetBits(GPIOC, GPIO_Pin_13);
vTaskDelay(500);
}
}
int main(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //开启GPIOC的时钟
//使用各个外设前必须开启时钟,否则对外设的操作无效
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式,赋值为推挽输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //GPIO引脚,赋值为第13号引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO速度,赋值为50MHz
GPIO_Init(GPIOC, &GPIO_InitStructure); //将赋值后的构体变量传递给GPIO_Init函数
//函数内部会自动根据结构体的参数配置相应寄存器
//实现GPIOC的初始化
/*设置GPIO引脚的高低电平*/
/*若不设置GPIO引脚的电平,则在GPIO初始化为推挽输出后,指定引脚默认输出低电平*/
// GPIO_SetBits(GPIOC, GPIO_Pin_13); //将PC13引脚设置为高电平
GPIO_ResetBits(GPIOC, GPIO_Pin_13); //将PC13引脚设置为低电平
xTaskCreate(myTask,"myTask",128,NULL,2,&myTaskHandler);
vTaskStartScheduler();
while (1)
{
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
进阶拓展
多任务示例
以下是一个创建两个任务的示例,一个控制LED闪烁,另一个在串口输出信息:
TaskHandle_t ledTaskHandler;
TaskHandle_t uartTaskHandler;
void ledTask(void *arg)
{
while(1)
{
GPIO_ResetBits(GPIOC, GPIO_Pin_13);
vTaskDelay(500);
GPIO_SetBits(GPIOC, GPIO_Pin_13);
vTaskDelay(500);
}
}
void uartTask(void *arg)
{
while(1)
{
printf("FreeRTOS running...\r\n");
vTaskDelay(1000);
}
}
int main(void)
{
// 初始化外设...
// 创建任务
xTaskCreate(ledTask, "LED", 128, NULL, 2, &ledTaskHandler);
xTaskCreate(uartTask, "UART", 128, NULL, 1, &uartTaskHandler);
// 启动调度器
vTaskStartScheduler();
// 正常情况下不会执行到这里
while(1);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
总结
通过以上步骤,我们成功地在STM32平台上创建了一个简单的FreeRTOS程序,并通过一个LED闪烁任务验证了程序的正确运行。FreeRTOS是一个功能强大的实时操作系统,它为嵌入式开发提供了多任务处理、任务间通信、资源管理等重要功能,能够极大地简化复杂嵌入式应用的开发。
在接下来的学习中,我们将进一步探索FreeRTOS的高级特性,如信号量、消息队列、任务通知等,以便开发更复杂、更强大的嵌入式应用。
更多资源
要深入学习FreeRTOS,可以参考以下资源:
参考文献
- FreeRTOS官方文档:https://www.freertos.org/Documentation/RTOS_book.html
- STM32标准外设库用户手册
- FreeRTOS源码解析
如有疑问,欢迎在评论区留言交流!您也可以在GitHub上提交Issue或Pull Request,共同改进这个项目。
第八章:FreeRTOS静态任务创建(2025.4.9巨详细)
评论记录:
回复评论: