珠海建网站的联系方式,广告设计专业专科学校有哪些,369网站建设中心,做品牌网站哪个好点本篇文章记录我在智能车竞赛中#xff0c;对 Infineon_TC264 这款芯片的底层库函数的学习分析。通过深入地对其库函数进行分析#xff0c;C语言深入的知识得以再次在编程中呈现和运用。故觉得很有必要在此进行记录一下。 目录
编辑 一、代码段
1、枚举类型
2、结构体 … 本篇文章记录我在智能车竞赛中对 Infineon_TC264 这款芯片的底层库函数的学习分析。通过深入地对其库函数进行分析C语言深入的知识得以再次在编程中呈现和运用。故觉得很有必要在此进行记录一下。 目录
编辑 一、代码段
1、枚举类型
2、结构体
3、看门狗
4、inline关键字
为什么使用inline
inline的限制和注意事项
5、ADC分辨率
6、__attribute__ 7、GCC
8、枚举型数组
1枚举型数组的定义和初始化
2枚举型数组的用法
3示例使用枚举型数组处理LED状态 一、代码段
1、枚举类型
typedef enum //定义了一个名为 IfxCpu_Id 的枚举类型。用户自定义数据类型增强器可读性
{IfxCpu_Id_0 0, /** \brief CPU 0 在枚举类型中如果没有指定值则第一个枚举成员默认为0之后的每一个美剧成员的值依次增加*/IfxCpu_Id_1 1, /** \brief CPU 1 */IfxCpu_Id_none /** \brief None of the CPU */
} IfxCpu_Id; 这段代码是用C语言编写的它定义了一个名为 IfxCpu_Id 的枚举类型。枚举Enumeration是一种用户定义的数据类型它允许程序员为整数类型分配更具有可读性的名称使代码更加清晰易懂。 在这个特定的例子中IfxCpu_Id 枚举被用来表示不同的 CPU 标识符。让我们逐个看看每个枚举成员及其含义 IfxCpu_Id_0 0这个成员代表 CPU 0。它被显式地赋值为 0。在枚举中如果没有指定值第一个枚举成员默认值是 0之后的每个枚举成员的值依次递增。 IfxCpu_Id_1 1这个成员代表 CPU 1。它被显式地赋值为 1。这里的赋值其实是可选的因为按照默认规则如果 IfxCpu_Id_0 被赋值为 0IfxCpu_Id_1 将自动被赋值为 1。但在这里显式指定可以增强代码的可读性和明确性。 IfxCpu_Id_none这个成员表示没有任何 CPU 被选中或者指定的操作不涉及特定的 CPU。注意到这个成员没有被显式地赋予一个特定的值。在枚举中如果前一个成员的值是 1那么 IfxCpu_Id_none 将自动被赋值为 2。这种自动赋值机制使得在枚举中添加新成员变得非常灵活无需手动调整其他成员的值。 2、结构体
void get_clock (void)
{// 获取时钟频率便于查看当前系统运行频率g_AppCpu0.info.pllFreq IfxScuCcu_getPllFrequency();g_AppCpu0.info.cpuFreq IfxScuCcu_getCpuFrequency(IfxCpu_getCoreIndex());g_AppCpu0.info.sysFreq IfxScuCcu_getSpbFrequency();g_AppCpu0.info.stmFreq IfxStm_getFrequency(MODULE_STM0);
} 代码片段中g_AppCpu0.info 是一个全局变量这里的 .info 指示它是一个结构体或者是一个包含结构体的更大结构体的成员。这个结构体至少包含了以下几个成员 pllFreq用于存储PLLPhase-Locked Loop锁相环频率的成员。这个成员的数据类型应该能够存储频率值通常是一个整数或浮点数。 cpuFreq用于存储CPU频率的成员。同样其数据类型应该是能够表示频率的整数或浮点数。 sysFreq用于存储系统外设总线SPBSystem Peripheral Bus频率的成员。其数据类型很可能与pllFreq和cpuFreq相同。 stmFreq用于存储系统定时管理器STMSystem Timer Module频率的成员。与其他频率成员类似其数据类型应该能够存储频率值。 结构体通常用于将逻辑上相关的数据组织在一起便于管理和访问。在这个例子中g_AppCpu0.info 结构体显然用于存储与系统频率相关的信息。这样的设计使得程序的其他部分可以方便地访问这些信息而不必关心这些信息是如何获取的。 虽然代码片段没有直接提供这个结构体的定义但我们可以根据上下文推断出它的大致结构。一个可能的定义如下使用C语言 typedef struct {float pllFreq; // PLL频率float cpuFreq; // CPU频率float sysFreq; // 系统外设总线频率float stmFreq; // 系统定时管理器频率
} SystemInfo;typedef struct {SystemInfo info; // 系统信息// 可能还有其他成员
} AppCpu;AppCpu g_AppCpu0; // 全局变量3、看门狗
void IfxScuWdt_disableCpuWatchdog(uint16 password)
{/* Select CPU Watchdog based on Core Id */uint32 coreId (uint32)IfxCpu_getCoreIndex();Ifx_SCU_WDTCPU *wdt MODULE_SCU.WDTCPU[coreId];IfxScuWdt_clearCpuEndinitInline(wdt, password);wdt-CON1.B.DR 1; //Set DR bit in Config_1 registerIfxScuWdt_setCpuEndinitInline(wdt, password);
}void IfxScuWdt_disableSafetyWatchdog(uint16 password)
{IfxScuWdt_clearSafetyEndinitInline(password);SCU_WDTS_CON1.B.DR 1; //Set DR bit in Config_1 registerIfxScuWdt_setSafetyEndinitInline(password);
}void IfxScuWdt_enableCpuWatchdog(uint16 password)
{/* Select CPU Watchdog based on Core Id */uint32 coreId (uint32)IfxCpu_getCoreIndex();Ifx_SCU_WDTCPU *wdt MODULE_SCU.WDTCPU[coreId];IfxScuWdt_clearCpuEndinitInline(wdt, password);wdt-CON1.B.DR 0; //Clear DR bit in Config_1 registerIfxScuWdt_setCpuEndinitInline(wdt, password);
}void IfxScuWdt_enableSafetyWatchdog(uint16 password)
{IfxScuWdt_clearSafetyEndinitInline(password);SCU_WDTS_CON1.B.DR 0; //Clear DR bit in Config_1 registerIfxScuWdt_setSafetyEndinitInline(password);
} 看门狗Watchdog Timer简称WDT是一种在计算机硬件或软件中常见的机制用于检测和恢复系统挂起例如由于软件错误导致的无限循环的情况。它的基本工作原理是计时器持续倒计时软件必须定期重置或“喂狗”这个计时器以防止它达到零。如果因为程序错误或其他原因导致软件未能在规定时间内重置看门狗计时器将到达零看门狗便会采取措施通常是重置系统以恢复正常操作。 看门狗的用途 系统恢复看门狗最主要的功能是在系统运行出现异常时自动进行系统重启尝试恢复系统正常运行。这对于需要高可靠性的嵌入式系统尤其重要例如医疗设备、工业控制系统等。 错误检测看门狗可以帮助检测系统中的错误状态。一些高级的看门狗定时器还可以提供错误日志或错误位置的记录功能帮助开发人员定位问题。 防止系统卡死在没有看门狗的情况下系统可能因为软件缺陷、硬件故障或外部干扰而卡死。看门狗确保了即使在这种情况下系统也能够自我恢复。 增强系统安全性在一些安全敏感的应用中看门狗可以防止恶意软件长时间控制系统。通过强制系统定期重启可以减少恶意软件造成持久性损害的机会。 看门狗的类型 硬件看门狗硬件看门狗是由微控制器或专用看门狗芯片实现的独立于主程序运行。它们通常更可靠因为即使主程序完全崩溃硬件看门狗仍然可以重置系统。 软件看门狗软件看门狗是在主程序中实现的通常通过操作系统提供的服务来实现。虽然软件看门狗的灵活性更高但它们依赖于操作系统的稳定性如果操作系统崩溃软件看门狗可能就无法正常工作。 结论 看门狗是提高系统可靠性和安全性的重要工具尤其在嵌入式系统设计中扮演着关键角色。通过确保系统能够在遇到无法从软件层面恢复的错误时自动重启看门狗帮助确保系统能够尽可能长时间地正常运行。 这些函数是用于控制Infineon微控制器上CPU看门狗定时器和安全看门狗定时器的启用和禁用的。它们通过修改特定的寄存器来实现对看门狗定时器的控制。下面是对每个函数的详细分析 IfxScuWdt_disableCpuWatchdog(uint16 password) 此函数的目的是禁用CPU看门狗定时器。它首先获取当前CPU核心的索引然后根据这个索引选择相应的CPU看门狗定时器实例。接着使用提供的密码暂时解除Endinit保护这是一种防止关键系统设置被意外或恶意更改的保护机制修改CON1寄存器的DR位为1这会禁用看门狗定时器最后重新设置Endinit保护。 IfxScuWdt_disableSafetyWatchdog(uint16 password) 此函数禁用安全看门狗定时器。与CPU看门狗定时器不同安全看门狗通常用于整个系统的安全监控。该函数使用提供的密码清除Endinit保护设置SCU_WDTS_CON1寄存器的DR位为1以禁用安全看门狗定时器然后重新设置Endinit保护。 IfxScuWdt_enableCpuWatchdog(uint16 password) 此函数启用CPU看门狗定时器。它的工作流程与禁用函数类似但是在修改CON1寄存器时将DR位清零这会启用看门狗定时器。 IfxScuWdt_enableSafetyWatchdog(uint16 password) 此函数启用安全看门狗定时器。它清除Endinit保护将SCU_WDTS_CON1寄存器的DR位清零以启用看门狗定时器然后重新设置Endinit保护。 密码和Endinit保护 所有这些函数都使用了一个名为password的参数来处理Endinit保护。Endinit保护是Infineon微控制器提供的一种机制旨在保护关键寄存器不被意外或恶意更改。要修改受保护的寄存器首先需要使用正确的密码清除Endinit保护完成修改后再重新设置保护。这增加了系统的安全性。 结构体访问 这些函数通过结构体和位字段访问和修改寄存器。例如wdt-CON1.B.DR语句访问了CON1寄存器的B位字段中的DR位。这种方式使得代码更易于阅读和维护同时也隐藏了底层硬件的复杂性。 总之这些函数提供了对Infineon微控制器上看门狗定时器的基本控制允许开发者根据需要启用或禁用这些重要的系统监视工具。 4、inline关键字
inline void ADC_Init(void)
{adc_init(ADC0_CH7_A7, ADC_12BIT); // 初始化对应 ADC 通道为对应精度
}inline是C和C语言中的一个关键字用于建议编译器对特定的函数进行内联展开而不是按照常规的函数调用机制进行调用。当一个函数被声明为inline时编译器会尝试将该函数的所有调用替换为函数本体的副本。这意味着在每个调用点编译器会插入整个函数的代码从而避免了函数调用的开销如参数传递、栈帧的创建和销毁等。 为什么使用inline 性能提升内联函数可以减少函数调用的开销对于小型且频繁调用的函数这可能会带来性能上的提升。 避免函数调用开销由于没有函数调用的额外开销使用inline可能会使得程序运行更快。 inline的限制和注意事项 编译器的自由度值得注意的是inline只是一个建议最终是否将函数内联以及如何内联取决于编译器的优化策略。现代编译器通常会对代码进行深入分析并自动决定哪些函数适合内联即使它们没有被显式地声明为inline。 代码膨胀过度使用内联可能会导致代码大小增加因为函数体的副本会在每个调用点插入。这可能会导致指令缓存命中率降低从而影响性能特别是在嵌入式系统或内存受限的环境中。 递归和大函数递归函数或较大的函数通常不适合内联因为这可能会导致栈溢出或代码膨胀。 5、ADC分辨率
typedef enum // 枚举ADC通道
{// ADC0可选引脚ADC0_CH0_A0 0*16 0,ADC0_CH1_A1,ADC0_CH2_A2,ADC0_CH3_A3,ADC0_CH4_A4,ADC0_CH5_A5,ADC0_CH6_A6,ADC0_CH7_A7,ADC0_CH8_A8,ADC0_CH10_A10 0*16 10,ADC0_CH11_A11,ADC0_CH12_A12,ADC0_CH13_A13,// ADC1可选引脚ADC1_CH0_A16 1*16 0,ADC1_CH1_A17 1*16 1,ADC1_CH4_A20 1*16 4,ADC1_CH5_A21 1*16 5,ADC1_CH8_A24 1*16 8,ADC1_CH9_A25 1*16 9,// ADC2可选引脚ADC2_CH3_A35 2*16 3,ADC2_CH4_A36,ADC2_CH5_A37,ADC2_CH6_A38,ADC2_CH7_A39,ADC2_CH10_A44 2*16 10,ADC2_CH11_A45,ADC2_CH12_A46,ADC2_CH13_A47,ADC2_CH14_A48,ADC2_CH15_A49,
}adc_channel_enum;// 此枚举定义不允许用户修改
typedef enum // 枚举ADC通道
{ADC_8BIT, // 8位分辨率ADC_10BIT, // 10位分辨率ADC_12BIT, // 12位分辨率
}adc_resolution_enum; 在电子和信号处理领域中分辨率是指系统能够区分或表示的最小单位或细节级别。对于模数转换器ADC来说分辨率通常是指数字信号中能够区分的最小幅度或最小变化量。 具体来说在ADC中分辨率通常以位数来表示比如8位、10位或12位等。这些位数表示了ADC输出的数字信号可以代表的离散级别数量。例如 8位ADC具有(2^8 256)个不同的离散级别即能够将模拟输入信号转换为0到255之间的数字。10位ADC具有(2^{10} 1024)个不同的离散级别即能够将模拟输入信号转换为0到1023之间的数字。12位ADC具有(2^{12} 4096)个不同的离散级别即能够将模拟输入信号转换为0到4095之间的数字。 更高的分辨率意味着ADC能够更准确地表示输入信号的细微变化因为它可以区分更多的离散级别。通常情况下更高的分辨率也意味着更高的精度但同时也会带来更高的数据传输和处理成本。 因此当谈论ADC的分辨率时我们通常指的是ADC能够将模拟输入信号转换为数字形式时的精确度和能力以及数字输出的位数和表示范围。 6、__attribute__
#define IFX_ALIGN(n) __attribute__ ((__align(n))) __attribute__ 是 GCC (GNU Compiler Collection) 提供的一种功能强大的语言扩展它允许程序员为函数、变量以及类型声明指定特殊的属性。这些属性可以用来控制编译器如何优化代码、如何对齐内存或者提供关于代码特性的附加信息从而提高程序的性能或可靠性。 上面的代码是一个宏定义用于简化 __attribute__((__align(n))) 属性的使用。这个属性指示编译器按照指定的字节对齐变量或数据结构。n 应该是2的幂并且是目标处理器支持的对齐方式。 如果希望某个结构体在内存中按照32字节对齐可以这样做 struct IFX_ALIGN(32) my_struct {int a;char b;// 其他成员
};这里的 IFX_ALIGN(32) 宏会展开为 __attribute__((__align(32)))告诉编译器这个结构体的实例需要按照32字节对齐。这种对齐通常用于提高内存访问的效率尤其是在需要频繁访问大量数据的高性能计算中非常有用。 需要注意的是__attribute__ 是GCC特有的扩展不是标准C或C的一部分。因此如果您的代码需要在不同的编译器上移植可能需要考虑使用条件编译或其他机制来确保兼容性。 7、GCC GCC全称GNU Compiler CollectionGNU编译器套件是一套由GNU项目开发的编程语言编译器。它是自由软件基金会Free Software Foundation, FSF的关键项目之一最初由理查德·斯托曼Richard Stallman在1985年发起旨在为GNU操作系统提供一个完全自由的编译器。GCC最初仅支持C语言编译但随着时间的推移它已经扩展到支持多种编程语言包括C、Objective-C、Fortran、Ada、Go和D等。 GCC是跨平台的可以在多种操作系统上运行包括Linux、macOS、Windows等同时支持多种处理器架构。它使用GPLGNU通用公共许可证发布意味着任何人都可以自由地使用、修改和分发GCC只要他们遵守GPL的条款。 GCC的特点和优势包括 跨平台和多语言支持GCC可以在多种操作系统上编译多种编程语言使其成为开发跨平台应用的强大工具。 优化能力GCC提供了广泛的优化选项允许开发者针对不同的应用场景和硬件配置调整代码以提高性能。 可移植性GCC生成的代码具有良好的可移植性能够在不同的硬件和操作系统环境中运行。 开源和自由作为自由软件GCC的源代码可供任何人查看和修改这促进了其不断的改进和发展。 广泛的应用GCC被广泛应用于学术界、工业界和开源社区是许多操作系统和嵌入式系统开发的首选编译器。 强大的社区支持由于GCC是开源项目它拥有一个活跃的社区社区成员贡献代码、修复bug并提供支持。 8、枚举型数组 枚举Enumeration是一种在C语言中用于定义常量的用户自定义数据类型它使得代码更加易读易潜。枚举型数组是指其元素类型为枚举类型的数组。这种数组可以有效地用于表示一系列固定选项或状态的集合使得代码的逻辑更清晰维护更简便。 1枚举型数组的定义和初始化
首先定义一个枚举类型
typedef enum {RED,GREEN,BLUE,YELLOW
} Color;然后你可以定义一个这种枚举类型的数组并进行初始化
Color colorArray[4] {RED, GREEN, BLUE, YELLOW};这里colorArray是一个包含4个元素的数组每个元素都是Color枚举类型分别被初始化为RED、GREEN、BLUE和YELLOW。 2枚举型数组的用法 状态机: 枚举型数组经常用于实现状态机其中数组的每个元素代表一个可能的状态。 配置选项: 如果你有一组固定的配置选项可以使用枚举型数组来存储当前配置。 映射值: 在需要将整数值映射到特定的标签或名称时可以使用枚举型数组。例如你可以根据枚举值索引数组来获取对应的字符串表示。 3示例使用枚举型数组处理LED状态 假设你正在编写一个程序来控制不同颜色的LED灯你可以使用枚举型数组来简化这个过程。 首先定义一个枚举来表示LED的状态 typedef enum {LED_OFF,LED_ON
} LEDState;然后如果你有多个LED灯可以定义一个枚举型数组来存储每个LED的状态 LEDState leds[4] {LED_OFF, LED_OFF, LED_OFF, LED_OFF};接下来你可以根据需要更改数组中特定LED的状态 // 打开第一个LED
leds[0] LED_ON;// 关闭第三个LED
leds[2] LED_OFF;通过使用枚举型数组你的代码更加清晰和易于理解同时也减少了错误的可能性。 总之枚举型数组是处理一组固定选项或状态的强大工具它提高了代码的可读性和可维护性。 注上面的代码之所以可以直接设定LED_ON和LED_OF是因为美剧类型的变量在没有赋初值的时候默认是从 0开始进行递增的。