HDMI-CEC STM32实现详解及代码示例
目录
一、HDMI-CEC基础知识
1.HDMI-CEC简介
2.HDMI-CEC功能描述
2.1 HDMI-CEC引脚说明
2.2 HDMI-CEC框图
2.3 消息描述
2.4 位时序说明
3.仲裁机制
3.1 SFT选项位配置说明
4.错误处理
4.1 位错误处理机制
4.2 消息错误处理规范
4.3 位上升沿错误(BRE)
4.4 短位周期错误(SBPE)
4.5 长位周期错误(LBPE)
4.6 传输错误检测(TXERR)
二、STM32的HAL库实现
编辑1.硬件条件
2.发起者配置
2.1 cubeMX配置
2.2 代码编写
3.跟随着配置
3.1 cubeMX配置
3.2 代码编写
4.效果演示
5.注意事项
一、HDMI-CEC基础知识
下面的内容大部分是翻译ST官方参考手册
1.HDMI-CEC简介
消费电子控制(CEC)是高清多媒体接口(HDMI)标准的一部分。它包含一套协议,可为各类视听设备提供高级控制功能。CEC以低速运行,对处理器和内存的开销要求极低。
STM32G071的HDMI-CEC控制器为该协议提供了硬件支持。
2.HDMI-CEC功能描述
2.1 HDMI-CEC引脚说明
CEC总线由一条双向传输线组成,用于设备的数据输入输出传输。该线路通过27kΩ上拉电阻连接至+3.3V电源电压。设备输出级必须采用开漏(open-drain)或集电极开路(open-collector)结构,以实现线与(wired-AND)连接。
HDMI-CEC控制器将CEC双向线路作为标准GPIO的复用功能进行管理,前提是该GPIO需配置为开漏复用模式。27kΩ上拉电阻必须外接于微控制器。
为避免应用断电时干扰CEC总线,必须在此情况下将CEC引脚与总线隔离。如图415所示,可通过MOS晶体管实现该隔离功能。
2.2 HDMI-CEC框图

2.3 消息描述
CEC线上的所有通信都由一个发起方(Initiator)和一个或多个跟随方(Follower)组成。发起方负责发送消息结构和数据,跟随方作为数据接收方负责设置确认位(ACK)。消息通过单帧传输,帧结构包含起始位(Start Bit)、头部块(Header Block),以及可选的操作码(Opcode)和可变数量的操作数块(Operand Blocks)。
每个数据块由8位有效载荷组成(最高位优先传输),后跟消息结束位(EOM)和确认位(ACK)。EOM位仅在消息最后一个数据块中置位,其余块保持复位状态。若在EOM指示后还存在额外数据块,接收方必须忽略这些数据块。EOM位可在头部块中置位用于"ping"其他设备以确认其活动状态。
确认位(ACK)始终由发起方设置为高阻抗,可由以下两种情况的跟随方驱动为低电平:在头部中识别到自身地址的跟随方,或需要拒绝广播消息的跟随方。头部结构包含源逻辑地址字段和目标逻辑地址字段,其中特殊地址0xF专用于广播消息。

2.4 位时序说明
起始位的格式具有唯一性,用于标识消息的开始。必须通过其低电平持续时间和总持续时间来验证起始位的有效性。
在起始位之后,消息中所有剩余数据位都保持一致的时序特性。每个数据位结束时的高电平到低电平转换将作为下一个数据位的起始,但最后一位数据除外——在最后一位数据结束后,CEC总线将保持高电平状态。

3.仲裁机制
所有需要在CEC总线上传输(或重传)消息的设备都必须确保总线在若干位周期内处于非活跃状态。这段空闲信号时间定义为从上一帧最后一位结束开始计算的时间,其具体长度取决于发起设备和当前状态,如下图所示。

由于同一时间只允许存在一个发起方,当多个发起方同时开始传输时,系统提供了仲裁机制来避免冲突。
CEC总线仲裁从起始位的前沿开始,持续到头部块中发起方地址位结束为止。在此期间,发起方必须持续监控CEC总线状态:如果在将总线驱动至高阻抗状态时检测到总线为低电平,则判定仲裁失败,此时应停止传输并转为跟随方模式。

图421展示了3个标定位周期的SFT示例。

在开始传输前,系统会计算一个可配置的时间窗口。
当SFT配置为0时,HDMI-CEC将自动计算SFT值以确保符合HDMI-CEC标准:
若当前CEC是上一次传输失败的发起方,则设置为2.5个数据位周期
若当前CEC是新的总线发起方,则设置为4个数据位周期
若当前CEC是上一次成功完成传输的发起方,则设置为6个数据位周期
这种机制可确保:
为失败的传输提供最高优先级
为成功完成传输的发起方分配最低优先级
此外,用户也可以通过配置SFT位来设置固定的时间值,可选值包括:0.5、1.5、2.5、3.5、4.5、5.5或6.5个数据位周期。
3.1 SFT选项位配置说明
当SFTOPT = 0时:
SFT计时从软件设置传输开始命令(TXSOM = 1)时开始计算。
当SFTOPT = 1时:
HDMI-CEC设备在检测到总线空闲或线路错误条件时会自动开始SFT计时。若在TXSOM命令设置时SFT计时已完成,则立即开始传输(无延迟);若SFT计时仍在进行,则系统需等待计时结束后才能开始传输。
当配置为SFTOPT = 1时,以下情况将触发SFT计时器启动:
在正常传输/接收结束时,当TXEND/RXEND位在消息最后一位(ACK位)的最小标称数据位持续时间被置位时,SFT计时器启动。
检测到传输错误时,当TXERR传输错误标志(TXERR = 1)被置位时立即启动计时器。
CEC跟随方未响应确认时,TXACKE位在ACK位的标称采样时间被置位将触发计时器启动。
发生传输欠载错误时,TXUDR位在ACK位结束时被置位会启动计时器。
检测到接收错误导致接收中止时,错误被检测到的同时计时器启动;若生成错误位,则在错误位结束时开始计时。
检测到错误起始位或总线非空闲低阻抗状态时,当总线恢复至高阻抗空闲状态时立即重启计时器。
4.错误处理
4.1 位错误处理机制
当检测到数据位无效时(起始位除外),跟随方应通过在CEC总线上生成一个低电平脉冲来通知该错误。该错误脉冲的持续时间必须为标准数据位周期的1.4至1.6倍(标准数据位周期为3.6毫秒)。

4.2 消息错误处理规范
当出现以下任一情况时,消息将被视为丢失并可能触发重传机制:
直接寻址消息未收到确认响应
广播消息收到否定确认
CEC总线在非预期时段检测到低阻抗状态(线路错误)
在接收数据位过程中,CEC接口可检测三类错误标志:
4.3 位上升沿错误(BRE)
当在位上升沿在预期时间窗口外被检测到时(参见图423),BRE(位上升沿错误)标志将被置位。若BREIE = 1,该标志还将触发CEC中断信号。
在检测到BRE(Bit Rising Error)的情况下,消息接收过程可根据BRESTP位的值停止,并且若BREGEN位置1,则会生成错误标志位。
当在广播消息中检测到BRE且BRESTP = 1时,即使BREGEN = 0,也会强制生成错误标志位,以确保发起方重新尝试失败的传输。
若需禁用错误标志生成,可配置 BREGEN = 0 且 BRDNOGEN = 1。
4.4 短位周期错误(SBPE)
当检测到信号下降沿早于预期时,SBPE 标志置位(参见图 423)。若 SBPEIE = 1,SBPE 标志还会触发 CEC 中断。
检测到 SBPE 错误时,总线上始终会生成错误标志位。仅在以下条件同时满足时,SBPE 检测不会生成错误标志位:
处于监听模式(LSTN = 1)
接收到的直接寻址消息包含 SBPE
或 接收到的广播消息包含 SBPE 且 BRDNOGEN = 1
4.5 长位周期错误(LBPE)
当在有效窗口内未检测到信号下降沿时,LBPE 标志置位(参见图 423)。若 LBPEIE = 1,LBPE 标志还会触发 CEC 中断。
LBPE 始终会停止接收过程。若 LBPEGEN = 1,总线上将生成错误标志位。
当广播消息中检测到 LBPE 时,即使 LBPEGEN = 0 也会强制生成错误标志位(以确保发起方重试传输)。
通过配置 LBPEGEN = 0 且 BRDNOGEN = 1 可禁用错误标志生成。
注意:应避免配置 BREGEN = 1 且 BRESTP = 0。

4.6 传输错误检测(TXERR)
当 CEC 发起方在传输高阻抗且未预期从设备断言位时,若检测到 CEC 线路存在低阻抗,则会设置 TXERR 标志。如果 TXERRIE = 1,TXERR 标志还会生成一个 CEC 中断。
TXERR 断言会停止消息传输。应用程序负责对失败的传输进行重试,最多可重试五次。
根据 CEC 线路的不同状态和 RX 容差配置,TXERR 检查的执行方式会有所不同。


二、STM32的HAL库实现
本文是使用的芯片是STM32F072实现的,该芯片有硬件CEC,而很多芯片是没有硬件CEC的,如果想知道一个芯片有没有硬件CEC,除了查参考手册外,还可以在STM32CubeMX上查看。在下图框内搜索,如果芯片有硬件CEC,则可以搜到。下面以STM32F072为例
1.硬件条件
按照官方文档需要一个上拉电阻,如果没有上拉电阻可能实现不了。但接下拉电阻一定实现不了(实验证明)。

2.发起者配置
2.1 cubeMX配置
时钟配置

因为STM32F072的最高频率是48MHz,所以下面填48

HDMI-CEC配置
GPIO配置

配置完项目地址后创建地址
2.2 代码编写
加入数组cec_send_buffer
/* Private variables ---------------------------------------------------------*/
CEC_HandleTypeDef hcec;
uint8_t cec_receive_buffer[16];
/* USER CODE BEGIN PV */
uint8_t cec_send_buffer[16] = {1,2,3,4,5,6,7,8,9};
/* USER CODE END PV */
while循环代码
while (1)
{
//地址是2
HAL_CEC_Transmit_IT(&hcec, 0, 2, cec_send_buffer, 14);
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
3.跟随着配置
3.1 cubeMX配置
cubeMX的配置和发起者一样
3.2 代码编写
把地址改为地址1,或者在cubeMX使能地址1。然后烧录即可。

4.效果演示
两块板子,一块是发起者,一块是跟随者,然后使用逻辑分析仪抓波形


5.注意事项
因为使用函数HAL_CEC_Transmit_IT发送数据,而参数InitiatorAddress和DestinationAddress分别是头部块的发起者和跟随者的地址,都是4位。
HAL_StatusTypeDef HAL_CEC_Transmit_IT(CEC_HandleTypeDef *hcec, uint8_t InitiatorAddress, uint8_t DestinationAddress, const uint8_t *pData, uint32_t Size)

但地址的宏定义是16位的,所以使用函数HAL_CEC_Transmit_IT输入的并不是官方的宏。以发到地址CEC_OWN_ADDRESS_1为例,函数HAL_CEC_Transmit_IT填入的目标地址应该是1,而不是CEC_OWN_ADDRESS_1。
下面以法发到地址CEC_OWN_ADDRESS_1为例
错误示范
![]()
正确做法
![]()
作者:嵌入式炒粉