AT32使用GPIO模拟HDMI CEC案例

AN0073
应用笔记
AT32使用GPIO模拟HDMI CEC案例 

前言
本应用笔记主要描述一种基于AT32 GPIO和定时器外设实现HDMI CEC简单收发功能的案例。
其中Consumer Electronics Control (CEC)是High Definition Multimedia Interface(HDMI)标准接口的一项功能,主要用于HDTV, DVDs等消费类电子产品音频、视频的信号控制。

注:本应用笔记对应的代码是基于雅特力提供的V2.x.x 板级支持包(BSP)而开发,对于其他版本BSP,需要注意使用上的区别。

支持型号列表:
支持型号    AT32全系列
 

1    概述
本应用笔记主要描述如何使用AT32的GPIO和定时器外设实现HDMI CEC功能。为便于介绍该案例,本文基于AT-START-F415开发板硬件环境进行展示。首先,本文介绍了基于AT32 HDMI CEC案例的系统结构;然后,介绍了HDMI CEC的帧格式和时序要求;最后,通过三块AT-START-F415分别作为三个device进行收发通信实验,实现HDMI CEC功能的展示。
2    AT32环境搭建
2.1    硬件资源
    AT32 HDMI CEC测试系统组成
测试系统主要有三块相同的AT-START-F415组成。
PB9:连接在一起作为CEC PIN,外部经过25 kΩ上拉到3.3 V。
PA9:作为USART TX信号,向PC端发送printf 调试信息。
PA0:USER Button, EXINT上升沿触发中断获取按键信号,MCU在成功获取按键后向对应device发送CEC控制信息。
GND:三块开发板GND相连。
图1. AT32 HDMI CEC测试系统组成
 
    AT32开发板
如下图为AT-START-F415 V1.0,且当前提供例程基于AT-START-F415(如果需要在AT32其他型号上运行,请更换为对应AT-START,并调整为对应型号底层驱动即可)。

图2. AT-START-F415 V1.0 实验板

2.2    软件资源
1)    SourceCode
    project\at_start_f415,MDK工程及main函数
    project\at32f415_board,开发板相关USART,LED等初始化函数
    project\hdmi_cec,CEC驱动库函数
    libraries,AT32外设库,基于V2.x.x BSP
2)    Doc
    AN0073_AT32使用GPIO模拟HDMI CEC案例
注:所有project都是基于keil 5而建立,若用户需要在其他编译环境上使用,请参考
AT32xxx_Firmware_Library_V2.x.x\project\at_start_xxx\templates中各种编译环境(例如IAR6/7,keil 4/5)进行简单修改即可。

2.3    HDMI CEC帧格式
主要针对CEC Message,CEC Farme,CEC Timing进行展开描述。
2.3.1    CEC Message
为实现特定的CEC feature,每一个CEC feature包含一条或多条CEC message。
每一条CEC message是单独的一帧,包含一个起始命令、一个Header Block和多个Data block。
CEC feature,CEC message和Block等相互关系如下图
图3. CEC feature数据结构

图4. CEC message 数据结构

2.3.2    CEC Frame
CEC总线单线全双工协议,最多可通过标准HDMI 线缆连接10个音频/视频设备。CEC信号传送主要包含Header Block和Data Block,对应的格式要求如下:
Header Block
Header Block包含逻辑源地址,逻辑目标地址,EOM bit(End of Message bit),ACK bit.
图5. CEC Header Block数据结构

 

Data Block
Data Block包含Information bits,EOM bit(End of Message bit),ACK bit.
图6. CEC Data Block数据结构

其中:
EOM bit :0表示message已传送完成,1表示还有data block待传送。
ACK bit :即Acknowledge bit,只有0表示ACK,1无效。

2.3.3    CEC Timing
Start Bit 时序要求
图7. CEC Start Bit 时序要求

        Data Bit时序要求
Data Bit,逻辑“0”时序要求如下图
图8. CEC Data Bit逻辑0时序要求

        Data Bit,逻辑“1”时序要求如下图
图9. CEC Data Bit逻辑1时序要求

2.3.4    HDMI CEC函数
由于篇幅有限,本文档主要描述cec_frame_receive和cec_frame_send的实现。
CEC接收函数cec_frame_receive
表1. CEC 接收帧描述

接收函数:CEC Pin PB9配置为open drain(CEC数据收发共用PB9),外部通过25 kΩ电阻上拉到3.3 V。配置TMR4通道4为输入捕获模式,下降沿有效。当CEC总线发出信号时,会立即进入TMR4 CC4捕获中断,在中断函数中再对接收数据进行解析。CEC接收帧的流程图如图10. CEC数据收发流程框图 A)所示。
同时,为了在接收帧过程中滤掉高频干扰信号,可通过在void cec_config(void)函数中配置tmr_input_channel_filter_set()函数进行滤波配置。

CEC发送函数cec_frame_send
表2. CEC 发送帧描述

发送函数:CEC Pin PB9配置为open drain,外部通过25 kΩ电阻上拉到3.3 V。将PA0,即USAER button配置为EXINT0 上升沿中断。在USAER button按下后,通过PB9输出CEC 信号,每次按键可切换信息发送到不同device ID.其流程图如图10. CEC数据收发流程框图所示。
图10. CEC数据收发流程框图
 
2.4    案例的快速使用
2.4.1    工程编译与下载
为了便于快速使用CEC demo,建议按如下步骤进行操作。
步骤一:
搭建 2.1 硬件资源所描述环境
步骤二:
打开AN0073_AT32_HDMI_CEC_By_GPIO_Simulation_V2.0.0\project\at_start_f415\templates\mdk_v5中Template.uvprojx工程
步骤三:
对三块开发板进行device编号,并在Keil上选择对应target进行全编译,然后下载到对应的开发板芯片上。
图11. CEC工程配置
 
步骤四:
按下其中一个开发板(比如Device编号为0A)的USER button,随即CEC帧信号从该开发板0A发送另一块开发板(比如Device编号为0B),再次按下该USER button,CEC帧信号从该开发板0A发送另一块开发板(比如Device编号为0C),其他开发板操作也是类似。
2.4.2    测试现象观察
逻辑分析仪分别抓取到的Device 0A to 0B和Device 0A to 0C的时序图如下:
图12. Device 0A to 0B时序图
 
图13. Device 0A to 0C时序图

串口调试信息
通过AT Link的虚拟串口功能,开发板的USART TX发送的数据可在电脑端串口助手观察到。
图14. CEC信息串口打印
 

3    版本历史
表3. 文档版本历史
日期    版本    变更
2021.11.29    2.0.0    最初版本
2023.05.19    2.0.1    优化部分表述



 

  • 14
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您解答这个问题。 在STM32上使用GPIO模拟UART来打印log,需要用到两个GPIO口,一个用于作为TX(发送)口,另一个用于作为RX(接收)口。 首先,需要在STM32的代码中定义两个GPIO口作为TX和RX口,并初始化它们的状态。然后,可以使用GPIO口的输出和输入功能来模拟UART的发送和接收。 在发送数据时,需要将数据转换为二进制格式,并将其逐位地发送到TX口。在接收数据时,需要从RX口逐位地读取数据,并将其转换为ASCII字符格式。 下面是一个使用GPIO模拟UART打印log的示例代码: ```c #include "stm32f10x.h" GPIO_InitTypeDef GPIO_InitStructure; void GPIO_UART_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* Configure USART Tx as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure USART Rx as input floating */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); } void GPIO_UART_SendChar(char ch) { uint8_t i; GPIO_WriteBit(GPIOA, GPIO_Pin_9, Bit_RESET); for(i=0;i<8;i++) { GPIO_WriteBit(GPIOA, GPIO_Pin_9, (BitAction)(ch & 0x01)); ch >>= 1; } GPIO_WriteBit(GPIOA, GPIO_Pin_9, Bit_SET); } void GPIO_UART_SendString(char *str) { while(*str) { GPIO_UART_SendChar(*str++); } } char GPIO_UART_ReceiveChar(void) { uint8_t i; char ch = 0; while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10)); for(i=0;i<8;i++) { ch >>= 1; if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10)) { ch |= 0x80; } while(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10)); } return ch; } int main(void) { GPIO_UART_Init(); GPIO_UART_SendString("Hello, world!\r\n"); while(1) { char ch = GPIO_UART_ReceiveChar(); GPIO_UART_SendChar(ch); } } ``` 在这个示例代码中,我们使用GPIOA的Pin9作为TX口,使用GPIOA的Pin10作为RX口。我们在GPIO_UART_Init()函数中初始化这两个GPIO口,并在GPIO_UART_SendChar()和GPIO_UART_ReceiveChar()函数中实现了模拟UART的发送和接收功能。在main()函数中,我们首先使用GPIO_UART_SendString()函数发送一条“Hello, world!”的log,然后使用GPIO_UART_ReceiveChar()函数循环接收并打印log。 希望这个示例代码可以帮助您理解如何在STM32上使用GPIO模拟UART来打印log。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值