[DemoCode下载] M051 CEC 协议的实作

[复制链接]
811|7
 楼主| wanduzi 发表于 2024-2-25 19:46 | 显示全部楼层 |阅读模式
TI, DA, ST, se, ce
EC_M051_CEC_V1.00.zip (821.87 KB, 下载次数: 0)
  1. /**********************************************************************************
  2. * [url=home.php?mod=space&uid=288409]@file[/url]    main.c
  3. * [url=home.php?mod=space&uid=247401]@brief[/url]    M051 CEC sample code
  4. *
  5. * [url=home.php?mod=space&uid=536309]@NOTE[/url]                                                                                                
  6. * Copyright(c) 2019 Nuvoton Technology Corp. All rights reserved.                                    
  7. *                                                                                                     
  8. ***********************************************************************************/
  9. #include <stdio.h>
  10. #include <stdint.h>
  11. #include "M051Series.h"
  12. #include    "Smpl_CEC.h"

  13. #define PLLCON_SETTING      CLK_PLLCON_50MHz_HXT
  14. #define PLL_CLOCK           50000000


  15. /*---------------------------------------------------------------------------------------------------------
  16. *CEC  command
  17. *---------------------------------------------------------------------------------------------------------*/
  18. #define Give_Physical_Address       0x83
  19. #define Give_Device_Power_Status    0x8f
  20. #define Set_Stream_Path             0x86
  21. #define User_Control_Pressed        0x44
  22. #define User_Control_Released       0x45
  23. #define System_Audio_Mode_Request   0x70
  24. #define Give_System_Audio_Mode_Status   0x7d
  25. #define Active_Source               0x82
  26. #define Get_CEC_Version             0x9f
  27. #define Give_Device_VendorID        0x8c
  28. #define Give_OSD_Name               0x46
  29. #define Feature_Abort               0x00

  30. #define Standby                     0x36




  31. void UART0_Init(void)
  32. {
  33.     /*---------------------------------------------------------------------------------------------------------*/
  34.     /* Init UART                                                                                               */
  35.     /*---------------------------------------------------------------------------------------------------------*/
  36.     /* Reset IP */
  37.     SYS_ResetModule(UART0_RST);

  38.     /* Configure UART0 and set UART0 Baudrate */
  39.     UART_Open(UART0, 115200);
  40. }
  41. void SYS_Init(void)
  42. {
  43.     /*---------------------------------------------------------------------------------------------------------*/
  44.     /* Init System Clock                                                                                       */
  45.     /*---------------------------------------------------------------------------------------------------------*/
  46.     /* Enable IRC22M clock */
  47.     CLK->PWRCON |= CLK_PWRCON_IRC22M_EN_Msk;

  48.     /* Waiting for IRC22M clock ready */
  49.     CLK_WaitClockReady(CLK_CLKSTATUS_IRC22M_STB_Msk);

  50.     /* Switch HCLK clock source to HIRC */
  51.     CLK->CLKSEL0 = CLK_CLKSEL0_HCLK_S_HIRC;

  52.     /* Set PLL to Power-down mode and PLL_STB bit in CLKSTATUS register will be cleared by hardware.*/
  53.     CLK->PLLCON |= CLK_PLLCON_PD_Msk;

  54.     /* Enable external 12 MHz XTAL */
  55.     CLK->PWRCON |= CLK_PWRCON_XTL12M_EN_Msk;

  56.     /* Enable PLL and Set PLL frequency */
  57.     CLK->PLLCON = PLLCON_SETTING;

  58.     /* Waiting for clock ready */
  59.     CLK_WaitClockReady(CLK_CLKSTATUS_PLL_STB_Msk | CLK_CLKSTATUS_XTL12M_STB_Msk);

  60.     /* Switch HCLK clock source to PLL, STCLK to HCLK/2 */
  61.     CLK->CLKSEL0 = CLK_CLKSEL0_STCLK_S_HXT | CLK_CLKSEL0_HCLK_S_PLL;

  62.     /* Enable peripheral clock */
  63.     CLK->APBCLK = CLK_APBCLK_UART0_EN_Msk | CLK_APBCLK_TMR3_EN_Msk;

  64.     /* Peripheral clock source */
  65.     CLK->CLKSEL1 = CLK_CLKSEL1_UART_S_PLL | CLK_CLKSEL1_TMR3_S_HXT;

  66.     /* Update System Core Clock */
  67.     /* User can use SystemCoreClockUpdate() to calculate PllClock, SystemCoreClock and CycylesPerUs automatically. */
  68.     SystemCoreClockUpdate();

  69.     /*---------------------------------------------------------------------------------------------------------*/
  70.     /* Init I/O Multi-function                                                                                 */
  71.     /*---------------------------------------------------------------------------------------------------------*/
  72.     /* Set P3 multi-function pins for UART0 RXD, TXD and T1 */
  73.     SYS->P3_MFP = SYS_MFP_P30_RXD0 | SYS_MFP_P31_TXD0 | SYS_MFP_P35_T1;
  74. }

  75. void TMR3_IRQHandler()
  76. {
  77.     TIMER3->TISR |= TIMER_TISR_TIF_Msk;
  78.     CEC_TimerEvent();
  79. }

  80. void CEC_SetTimer(uint32_t  us)
  81. {
  82.     TIMER3->TCMPR = us * 12;
  83.     TIMER3->TCSR |= TIMER_TCSR_CEN_Msk; //start count
  84. }

  85. void EINT1_IRQHandler()
  86. {
  87.     GPIO_CLR_INT_FLAG(P3, BIT3);

  88.     NVIC_DisableIRQ(CECExtInt);//disable CEC int pin
  89.     CEC_SetTimer(1000);

  90.     if ((u8CECTRStatus == CECReceive) && (u8CECState == 1) && (u8CECTimerCNT == 9))
  91.     {
  92.         if (u8CECReAckFlag == 1)
  93.             CEC_SetTimer(10);   //if reply ACK, timer interrupt need not wait 1ms
  94.     }

  95.     u8CECEIntStatus = 0xff;
  96.     u8CECTRStatus = CECReceive;
  97. }

  98. void    ClearExtInt()
  99. {
  100.     if (CECExtInt == EINT1_IRQn)
  101.         GPIO_CLR_INT_FLAG(P3, BIT3);

  102.     if (CECExtInt == EINT0_IRQn)
  103.         GPIO_CLR_INT_FLAG(P3, BIT2);
  104. }

  105. void CECSetReceive()        //CEC initial receive mode
  106. {
  107.     u8CECState = u8CECEIntStatus = u8CECTimerCNT = u8CECSubCNT =
  108.                                                  u8CECEOM = 0;
  109.     u8CECTRStatus = CECIdle;
  110.     GPIO_SetMode(CECPort, CECPin, GPIO_PMD_INPUT);
  111.     GPIO_SET_DEBOUNCE_TIME(GPIO_DBCLKSRC_HCLK, GPIO_DBCLKSEL_4);
  112.     GPIO_ENABLE_DEBOUNCE(CECPort, CECPin);
  113.     GPIO_EnableEINT1(P3, 3, GPIO_INT_FALLING);
  114.     NVIC_EnableIRQ(EINT1_IRQn);
  115. }
  116. void InitialCEC()
  117. {
  118.     u8CECRetranCNT = 0;

  119.     TIMER3->TCSR |= TIMER_TCSR_CRST_Msk;
  120.     TIMER3->TCSR = TIMER_ONESHOT_MODE | TIMER_TCSR_IE_Msk | TIMER_TCSR_TDR_EN_Msk;
  121.     TIMER3->TCMPR = 0xffffff;
  122.     NVIC_EnableIRQ(TMR3_IRQn);      //enable timer interrupt
  123.     CECSetReceive();
  124. }

  125. void UnInitialCEC()
  126. {
  127.     u8CECRetranCNT = 0;

  128.     NVIC_DisableIRQ(TMR3_IRQn);     //disable timer interrupt
  129.     GPIO_DisableInt(P3, 3);         //disable EXT1 interrupt
  130. }

  131. /**
  132. * @brief This function is transfer data
  133. * @param[in] DataLength, total data to be Tx
  134. * [url=home.php?mod=space&uid=266161]@return[/url] none
  135. * @note this functun is called when user want to Tx data, user must assure u8CECTRStatus is CECIdle then call this function,
  136. * other wise will cause the protocal break down
  137. *
  138. */
  139. void SendData(uint8_t   DataLength)
  140. {
  141.     uint8_t u8Temp;
  142.     u8CECState = u8CECEIntStatus = u8CECTimerCNT = u8CECSubCNT = u16CECAckFlag = u16CECAckCheckFlag =
  143.                                                                              u8CECEOM = 0;
  144.     u8CECTRStatus = CECtransmit;
  145.     u8CECTxLength = u8CECTxRemain = DataLength;

  146.     u8Temp = (au8CECTxData[0] >> 4) & 0x0f;

  147.     if (u8Temp == (au8CECTxData[0] & 0x0f)) //dest=source,general call
  148.         u16CECAckCheckFlag = 0;
  149.     else
  150.     {
  151.         for (u8Temp = 0; u8Temp < DataLength; u8Temp++)
  152.         {
  153.             u16CECAckCheckFlag |= 0x8000 >> u8Temp;
  154.         }
  155.     }

  156.     GPIO_SetMode(CECPort, CECPin, GPIO_PMD_OPEN_DRAIN);
  157.     GPIO_DisableInt(P3, 3);         //disable EXT1 interrupt

  158.     P33 = 1;    //CEC pin set high
  159.     CEC_SetTimer(500);      //start check free time every 0.5ms, free time over than 5ms, you can send data
  160. }



  161. /**
  162. * @brief This function is send CEC command
  163. * @param[in] CECCommand, command index
  164. * @return none
  165. * @note this functun is called when user want to send CEC command
  166. *
  167. */
  168. void SendCECCommand(uint8_t CECCommand)
  169. {
  170.     while (u8CECTRStatus != CECIdle);     //wait CEC bus enter idle state, then start transmit

  171.     switch (CECCommand)
  172.     {
  173.         case    Standby:        //
  174.             au8CECTxData[1] = Standby;
  175.             u8CECTxLength = 2;                  //total data length should be send
  176.             SendData(u8CECTxLength);

  177.             while (u8CECTRStatus != CECIdle)        //waitting CEC data transfer over, customer can run their code, and check this flag in main loop
  178.                 ;

  179.             printf("ACKbit=:0x %x, \n", u16CECAckFlag);
  180.             break;

  181.         case    System_Audio_Mode_Request:      //
  182.             au8CECTxData[1] = System_Audio_Mode_Request;
  183.             au8CECTxData[2] = 0x20;    //this need the phisical address
  184.             au8CECTxData[3] = 0x00;    //this need the phisical address
  185.             u8CECTxLength = 4;
  186.             SendData(u8CECTxLength);

  187.             while (u8CECTRStatus != CECIdle)
  188.                 ;

  189.             printf("ACKbit=:0x %x, \n", u16CECAckFlag);
  190.             break;

  191.         case    Set_Stream_Path:        //
  192.             au8CECTxData[0] |= 0xf;
  193.             au8CECTxData[1] = Set_Stream_Path;
  194.             au8CECTxData[2] = 0x20;    //this need the phisical address
  195.             au8CECTxData[3] = 0x00;    //this need the phisical address
  196.             u8CECTxLength = 4;
  197.             SendData(u8CECTxLength);

  198.             while (u8CECTRStatus != CECIdle)
  199.                 ;

  200.             printf("ACKbit=:0x %x, \n", u16CECAckFlag);
  201.             break;

  202.         case    Give_Device_Power_Status:
  203.             au8CECTxData[1] = Give_Device_Power_Status;
  204.             u8CECTxLength = 2;
  205.             SendData(u8CECTxLength);

  206.             while (u8CECTRStatus != CECIdle)
  207.                 ;

  208.             printf("ACKbit=:0x %x, \n", u16CECAckFlag);
  209.             break;

  210.         case    Give_Physical_Address:
  211.             au8CECTxData[1] = Give_Physical_Address;
  212.             u8CECTxLength = 2;
  213.             SendData(u8CECTxLength);

  214.             while (u8CECTRStatus != CECIdle)
  215.                 ;

  216.             printf("ACKbit=:0x %x, \n", u16CECAckFlag);
  217.             break;

  218.         case    User_Control_Released:
  219.             au8CECTxData[1] = User_Control_Released;
  220.             u8CECTxLength = 2;
  221.             SendData(u8CECTxLength);

  222.             while (u8CECTRStatus != CECIdle)
  223.                 ;

  224.             printf("ACKbit=:0x %x, \n", u16CECAckFlag);
  225.             break;

  226.         case    User_Control_Pressed:
  227.             au8CECTxData[1] = User_Control_Pressed;
  228.             au8CECTxData[2] = 0x21; //0x21,number1, is [UI Command],please refer the CEC table 27 UserControlCode
  229.             u8CECTxLength = 3;
  230.             SendData(u8CECTxLength);

  231.             while (u8CECTRStatus != CECIdle)
  232.                 ;

  233.             printf("ACKbit=:0x %x, \n", u16CECAckFlag);
  234.             break;

  235.         case    Give_System_Audio_Mode_Status:
  236.             au8CECTxData[1] = Give_System_Audio_Mode_Status;
  237.             u8CECTxLength = 2;
  238.             SendData(u8CECTxLength);

  239.             while (u8CECTRStatus != CECIdle)
  240.                 ;

  241.             printf("ACKbit=:0x %x, \n", u16CECAckFlag);
  242.             break;

  243.         case    Give_OSD_Name:
  244.             au8CECTxData[1] = Give_OSD_Name;
  245.             u8CECTxLength = 2;
  246.             SendData(u8CECTxLength);

  247.             while (u8CECTRStatus != CECIdle)
  248.                 ;

  249.             printf("ACKbit=:0x %x, \n", u16CECAckFlag);
  250.             break;

  251.         case    Give_Device_VendorID:
  252.             au8CECTxData[1] = Give_Device_VendorID;
  253.             u8CECTxLength = 2;
  254.             SendData(u8CECTxLength);

  255.             while (u8CECTRStatus != CECIdle)
  256.                 ;

  257.             printf("ACKbit=:0x %x, \n", u16CECAckFlag);
  258.             break;

  259.         case    Get_CEC_Version:
  260.             au8CECTxData[1] = Get_CEC_Version;
  261.             u8CECTxLength = 2;
  262.             SendData(u8CECTxLength);

  263.             while (u8CECTRStatus != CECIdle)
  264.                 ;

  265.             printf("ACKbit=:0x %x, \n", u16CECAckFlag);
  266.             break;

  267.         case    Active_Source:
  268.             au8CECTxData[1] = Active_Source;
  269.             au8CECTxData[2] = 4;
  270.             au8CECTxData[3] = 0;
  271.             u8CECTxLength = 3;
  272.             SendData(u8CECTxLength);

  273.             while (u8CECTRStatus != CECIdle)
  274.                 ;

  275.             printf("ACKbit=:0x %x, \n", u16CECAckFlag);
  276.             break;

  277.         default:
  278.             break;
  279.     }

  280. }

  281. /**
  282. * @brief This function used to decode command from received data package
  283. * @param[in] none
  284. * @return none
  285. * @note this functun is called when user received a CEC data package
  286. *
  287. */
  288. void CECDecoderCommand()
  289. {
  290.     while (u8CECTRStatus != CECIdle);

  291.     if (u8CECLogicalAddr == (au8CECRxData[0] & 0xf))
  292.     {
  293.         if (au8CECRxData[1] == 0xff)   //abort message
  294.         {
  295.             u8CECSrcAddr = 4;
  296.             u8CECDstAddr = (au8CECRxData[0] & 0xf0) >> 4;
  297.             au8CECTxData[0] = 0;
  298.             au8CECTxData[0] = (u8CECSrcAddr << 4) | u8CECDstAddr;

  299.             au8CECTxData[1] = Feature_Abort; //feature abort
  300.             au8CECTxData[2] = 0xff;    //abort reason
  301.             au8CECTxData[3] = 4;   //
  302.             u8CECTxLength = 4;
  303.             SendData(u8CECTxLength);

  304.             while (u8CECTRStatus != CECIdle)
  305.                 ;

  306.             printf("ACKbit=:0x %x, \n", u16CECAckFlag);
  307.         }

  308.         if (au8CECRxData[1] == Give_Physical_Address) //Give phisical address command
  309.         {
  310.             u8CECSrcAddr = 4;
  311.             u8CECDstAddr = 0xf;   //broadcast message
  312.             au8CECTxData[0] = 0;
  313.             au8CECTxData[0] = (u8CECSrcAddr << 4) | u8CECDstAddr;

  314.             au8CECTxData[1] = 0x84; //report physical address
  315.             au8CECTxData[2] = 0x20;    //physical address
  316.             au8CECTxData[3] = 0x00;    //physical address
  317.             au8CECTxData[4] = 0x4;     //device type
  318.             u8CECTxLength = 5;
  319.             SendData(u8CECTxLength);

  320.             while (u8CECTRStatus != CECIdle)
  321.                 ;

  322.             printf("ACKbit=:0x %x, \n", u16CECAckFlag);
  323.         }

  324.     }

  325. }


  326. int32_t main()
  327. {
  328.     uint32_t    i, j;

  329.     /* Unlock protected registers */
  330.     SYS_UnlockReg();

  331.     /* Init System, peripheral clock and multi-function I/O */
  332.     SYS_Init();

  333.     /* Lock protected registers */
  334.     SYS_LockReg();

  335.     UART0_Init();
  336.     printf("CED demo \n");

  337.     u8CECSrcAddr = 0x2;
  338.     u8CECDstAddr = 0x3;

  339.     GPIO_SetMode(P3, BIT3, GPIO_PMD_QUASI);


  340.     for (i = 0; i < CECMaxPayload; i++)
  341.         au8CECTxData[i] = 0;

  342.     au8CECTxData[0] = (u8CECSrcAddr << 4) | u8CECDstAddr;

  343.     for (i = 1; i < CECMaxPayload; i++)
  344.         au8CECTxData[i] = u8CECSrcAddr;

  345.     InitialCEC();

  346.     u8CECLogicalAddr = u8CECSrcAddr;


  347.     while (1)
  348.     {
  349.         if (u8CECTRStatus == CECIdle)
  350.         {
  351.             SendCECCommand(Standby);
  352.         }

  353.         for (i = 0; i < 1000; i++)
  354.         {
  355.             CLK_SysTickDelay(1000);

  356.             if (u8CECGetData)       //received  CEC data from CEC line
  357.             {
  358.                 u8CECGetData = 0;
  359.                 printf("Received:");

  360.                 for (j = 0; j < u8CECRxLength; j++)
  361.                     printf("%x, ", au8CECRxData[j]);

  362.                 printf(" \n");
  363.                 CECDecoderCommand();        //decoder received CEC command

  364.                 for (j = 0; j < CECMaxPayload; j++)
  365.                     au8CECRxData[j] = 0;
  366.             }
  367.         }

  368.     }
  369. }
  370. /*  Copyright(c) 2019 Nuvoton Technology Corp. All rights reserved.     */






 楼主| wanduzi 发表于 2024-2-25 19:46 | 显示全部楼层
  1. /**************************************************************************//**
  2. * @file    CEC_Lib.c
  3. * @brief   CEC protocal stack
  4. *          Transmit, receive and retransmit CEC data
  5. * @note
  6. * Copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
  7. *
  8. *****************************************************************************/
  9. #include <stdio.h>
  10. #include <stdint.h>
  11. #include "M051Series.h"
  12. #include "Smpl_CEC.h"

  13. uint8_t au8CECTxData[CECMaxPayload], au8CECRxData[CECMaxPayload];
  14. //define
  15. //au8CECTxData[0]--header
  16. //au8CECTxData[1]--data1
  17. //...

  18. volatile uint8_t  u8CECTxLength;
  19. uint8_t u8CECState, u8CECTRStatus, u8CECLogicalAddr, u8CECPhysicalAddr,
  20.         u8CECTxRemain, u8CECRxLength, u8CECEOM, u8CECGetData;

  21. uint8_t u8CECEIntStatus, u8CECTimerCNT, u8CECRetranCNT, u8CECSubCNT, u8CECSrcAddr, u8CECDstAddr;
  22. uint8_t u8CECErrorFlag, u8CECReAckFlag;

  23. uint16_t    u16CECAckFlag, u16CECAckCheckFlag;
  24. //u16CECAckFlag define
  25. //#define   HeadAck 0x8000
  26. //#define   Data1Ack    0x4000
  27. //#define   Data2Ack    0x2000
  28. //#define   Data3Ack    0x1000
  29. //......
  30. //#define   Data15Ack   0x0001



  31. /**
  32. * @brief This function do all CEC protocal stack
  33. * @param[in] none
  34. * @return none
  35. * @note this functun is called from Timer3 interrupt
  36. *
  37. */

  38. void CEC_TimerEvent()
  39. {
  40. uint8_t u8Temp;

  41.     if (u8CECTRStatus == CECtransmit) //  CEC in trasmit process
  42.     {
  43.         switch (u8CECState)
  44.         {
  45.             case    0:          //check bus free time for 5bit data period
  46.                 if (P33 == 1)
  47.                 {
  48.                     CEC_SetTimer(500);
  49.                     u8CECTimerCNT++;

  50.                     if (u8CECTimerCNT > 24)
  51.                     {
  52.                         CEC_SetTimer(3700);
  53.                         u8CECState = 1;
  54.                         u8CECTimerCNT = 0;
  55.                         P33 = 0; //CECpin low, start bit
  56.                     }
  57.                 }
  58.                 else
  59.                 {
  60.                     CECSetReceive();
  61.                     CEC_SetTimer(5000); //check if data need retransmit
  62.                     u8CECTimerCNT = 0;
  63.                     //printf("send fail, turn to receiver  \n");
  64.                 }

  65.                 break;

  66.             case    1:      //send head and check arbitration
  67.             {
  68.                 if (u8CECTimerCNT == 0)
  69.                 {
  70.                     P33 = 1; //start bit high level

  71.                     for (u8Temp = 20; u8Temp >0; u8Temp--);

  72.                     if (P33 == 0) //start bit arbitration lost
  73.                     {
  74.                         //printf("start bit arbitration lost  \n");
  75.                         CECSetReceive();        //turn to receive mode
  76.                         CEC_SetTimer(5000); //check if data need retransmit
  77.                         return;
  78.                     }
  79.                     else
  80.                     {
  81.                         CEC_SetTimer(800);      //start bit ,high level  0.8 ms
  82.                         u8CECTimerCNT++;
  83.                         u8CECSubCNT = 0;
  84.                     }
  85.                 }
  86.                 else if (u8CECTimerCNT < 9)   //send head data
  87.                 {
  88.                     if (u8CECSubCNT == 0)
  89.                     {
  90.                         P33 = 0; //data bit start

  91.                         if (au8CECTxData[0] & (0x80 >> (u8CECTimerCNT - 1)))
  92.                             CEC_SetTimer(600);//bit 1, low level 0.6ms
  93.                         else
  94.                             CEC_SetTimer(1500);//bit 0, low level 1.5ms

  95.                         u8CECSubCNT = 1;
  96.                         //printf("head bit :%d   \n",u8CECTimerCNT);
  97.                     }
  98.                     else
  99.                     {
  100.                         P33 = 1; //CECpin high

  101.                         for (u8Temp = 30; u8Temp >0; u8Temp--);

  102.                         if (P33 == 0) //arbitration lost
  103.                         {
  104.                             printf("head bit :%d arbitration lost  \n", u8CECTimerCNT);
  105.                             //u8CECTxLength=0;    //arbitration lost ,stop tran
  106.                             CECSetReceive();        //turn to receive mode
  107.                             CEC_SetTimer(15000);//must wait 15ms then retrans, check if data need retransmit
  108.                             return;
  109.                         }
  110.                         else
  111.                         {
  112.                             if (au8CECTxData[0] & (0x80 >> (u8CECTimerCNT - 1)))
  113.                                 CEC_SetTimer(1790);//bit 1, high level 1.8 ms
  114.                             else
  115.                                 CEC_SetTimer(890);//bit 0, high level 0.9 ms

  116.                             u8CECTimerCNT++;
  117.                             u8CECSubCNT = 0;
  118.                         }

  119.                     }
  120.                 }
  121.                 else if (u8CECTimerCNT == 9)  //EOM bit
  122.                 {

  123.                     if (u8CECSubCNT == 0) //EOM bit low level
  124.                     {
  125.                         P33 = 0; //EOM bit start

  126.                         if (u8CECTxRemain > 1)
  127.                             CEC_SetTimer(1500);//bit 0, low level 1.5ms
  128.                         else
  129.                             CEC_SetTimer(600);//bit 1, low level 0.6ms

  130.                         u8CECSubCNT = 1;
  131.                     }
  132.                     else
  133.                     {
  134.                         P33 = 1; //EOM bit start

  135.                         if (u8CECTxRemain > 1)
  136.                             CEC_SetTimer(900);//bit 0, high level 0.9ms
  137.                         else
  138.                             CEC_SetTimer(1800);//bit 1, high level 1.8ms

  139.                         u8CECSubCNT = 0;
  140.                         u8CECTimerCNT++;
  141.                     }
  142.                 }
  143.                 else if (u8CECTimerCNT == 10)     //ACK bit
  144.                 {
  145.                     if (u8CECSubCNT == 0)
  146.                     {
  147.                         CEC_SetTimer(600);
  148.                         P33 = 0; //ACK bit low level
  149.                         u8CECSubCNT = 1;
  150.                     }
  151.                     else if (u8CECSubCNT == 1)
  152.                     {
  153.                         CEC_SetTimer(400);
  154.                         P33 = 1; //ACK bit high level
  155.                         u8CECSubCNT = 2;
  156.                     }
  157.                     else if (u8CECSubCNT == 2)     //check ack bit at 1ms positon
  158.                     {
  159.                         CEC_SetTimer(1400);

  160.                         if (P33 == 0) //get ack bit
  161.                         {
  162.                             u16CECAckFlag |= 0x8000;
  163.                         }

  164.                         u8CECSubCNT = 0;
  165.                         u8CECTimerCNT = 0;
  166.                         u8CECState = 2;
  167.                         u8CECTxRemain--;
  168.                     }

  169.                 }

  170.             }
  171.             break;

  172.             case    2:      //transmit all data
  173.             {
  174.                 if (u8CECTxRemain)
  175.                 {
  176.                     if (u8CECTimerCNT < 8)
  177.                     {
  178.                         if (u8CECSubCNT == 0)
  179.                         {
  180.                             P33 = 0; //data bit start

  181.                             if (au8CECTxData[u8CECTxLength - u8CECTxRemain] & (0x80 >> u8CECTimerCNT))
  182.                                 CEC_SetTimer(600);//bit 1, low level 0.6ms
  183.                             else
  184.                                 CEC_SetTimer(1500);//bit 0, low level 1.5ms

  185.                             u8CECSubCNT = 1;
  186.                         }
  187.                         else
  188.                         {
  189.                             P33 = 1; //CECpin high

  190.                             if (au8CECTxData[u8CECTxLength - u8CECTxRemain] & (0x80 >> u8CECTimerCNT))
  191.                                 CEC_SetTimer(1800);//bit 1, high level 1.8 ms
  192.                             else
  193.                                 CEC_SetTimer(900);//bit 0, high level 0.9 ms

  194.                             u8CECTimerCNT++;
  195.                             u8CECSubCNT = 0;
  196.                         }
  197.                     }
  198.                     else if (u8CECTimerCNT == 8)  //EOM bit
  199.                     {
  200.                         if (u8CECSubCNT == 0) //EOM bit low level
  201.                         {
  202.                             P33 = 0; //EOM bit start

  203.                             if (u8CECTxRemain > 1)
  204.                                 CEC_SetTimer(1500);//bit 0, low level 1.5ms
  205.                             else
  206.                                 CEC_SetTimer(600);//bit 1, low level 0.6ms

  207.                             u8CECSubCNT = 1;
  208.                         }
  209.                         else
  210.                         {
  211.                             P33 = 1; //EOM bit start

  212.                             if (u8CECTxRemain > 1)
  213.                                 CEC_SetTimer(900);//bit 0, high level 0.9ms
  214.                             else
  215.                                 CEC_SetTimer(1800);//bit 1, high level 1.8ms

  216.                             u8CECSubCNT = 0;
  217.                             u8CECTimerCNT++;
  218.                         }
  219.                     }
  220.                     else if (u8CECTimerCNT == 9)  //ACK bit
  221.                     {
  222.                         if (u8CECSubCNT == 0)
  223.                         {
  224.                             CEC_SetTimer(600);
  225.                             P33 = 0; //ACK bit low level
  226.                             u8CECSubCNT = 1;
  227.                         }
  228.                         else if (u8CECSubCNT == 1)
  229.                         {
  230.                             CEC_SetTimer(400);
  231.                             P33 = 1; //ACK bit high level
  232.                             u8CECSubCNT = 2;
  233.                         }
  234.                         else if (u8CECSubCNT == 2)     //check ack bit at 1ms positon
  235.                         {
  236.                             CEC_SetTimer(1400);

  237.                             if (P33 == 0) //get ack bit
  238.                             {
  239.                                 u16CECAckFlag |= 0x8000 >> (u8CECTxLength - u8CECTxRemain);
  240.                             }

  241.                             u8CECSubCNT = 0;
  242.                             u8CECTimerCNT = 0;
  243.                             u8CECTxRemain--;
  244.                         }

  245.                     }
  246.                 }
  247.                 else    //all data transmit out
  248.                 {
  249.                     if (u16CECAckFlag != u16CECAckCheckFlag)  //check ack, if not match, retransmit data
  250.                     {
  251.                         if (((au8CECTxData[0] >> 4) & 0x0f) == (au8CECTxData[0] & 0x0f))
  252.                         {
  253.                             //check general call, no need retransmit
  254.                             u8CECTxLength = u8CECRetranCNT = 0;
  255.                             CECSetReceive();        //turn to receive mode
  256.                             return;
  257.                         }
  258.                         else
  259.                         {
  260.                             u8CECRetranCNT++;

  261.                             //printf("retrans :%d times  \n", u8CECRetranCNT);
  262.                             if (u8CECRetranCNT > 4)   //retrans fail 5 times, abort transmit!
  263.                             {
  264.                                 u8CECTxLength = u8CECRetranCNT = 0;
  265.                                 CECSetReceive();        //turn to receive mode
  266.                                 return;
  267.                             }

  268.                             SendData(u8CECTxLength);
  269.                             //CECSetReceive();
  270.                             //CEC_SetTimer(3000);   //check if data need retransmit
  271.                         }
  272.                     }
  273.                     else
  274.                     {
  275.                         u8CECTxLength = u8CECRetranCNT = 0;
  276.                         CECSetReceive();        //turn to receive mode
  277.                         return;
  278.                     }
  279.                 }
  280.             }
  281.             break;
  282.         }

  283.     }
  284.     else if (u8CECTRStatus == CECReceive)
  285.     {
  286.         if (u8CECEIntStatus == 0)
  287.         {
  288.             CECSetReceive();    //timer is not trigged by ext int, it's means last trigger is a noise
  289.             CEC_SetTimer(5000); //check if data need transmit
  290.             //printf("Noise trigger, checked 1\n");
  291.             return;
  292.         }

  293.         switch (u8CECState)
  294.         {
  295.             case    0:      //receive check start bit
  296.             {
  297.                 if (u8CECTimerCNT < 5)
  298.                 {
  299.                     if (P33 == 1)
  300.                     {
  301.                         //it's noise,not start bit
  302.                         //printf("Noise trigger, checked2: %d \n",u8CECTimerCNT);
  303.                         CECSetReceive();
  304.                         return;
  305.                     }
  306.                     else
  307.                     {
  308.                         u8CECTimerCNT++;

  309.                         if (u8CECTimerCNT == 5)
  310.                             CEC_SetTimer(1100);
  311.                         else
  312.                             CEC_SetTimer(500);
  313.                     }

  314.                 }
  315.                 else if (u8CECTimerCNT == 5)
  316.                 {
  317.                     if (P33 == 0)
  318.                     {
  319.                         //it's noise,not start bit
  320.                         //printf("Noise trigger, checked 3\n");
  321.                         CECSetReceive();
  322.                         return;
  323.                     }
  324.                     else
  325.                     {
  326.                         u8CECTimerCNT = u8CECRxLength = u8CECErrorFlag = 0;
  327.                         u8CECState = 1;
  328.                         NVIC_EnableIRQ(CECExtInt);  //enable ext int check
  329.                         u8CECEIntStatus = 0;      //check if the timer is trigged from ext int
  330.                         CEC_SetTimer(1000000);      //for safe,
  331.                         //printf("Get start bit\n");
  332.                     }
  333.                 }
  334.             }
  335.             break;

  336.             case    1:
  337.             {
  338.                 if (u8CECErrorFlag == 0xff)
  339.                 {           //user can add error process here:
  340.                     /*                  u8CECState=2;
  341.                                         u8CECErrorFlag=u8CECTimerCNT=u8CECSubCNT=u8CECRxLength=0;
  342.                                         //NVIC_DisableIRQ(CECExtInt);   //enable ext int check
  343.                                         GPIO_SetMode(CECPort, CECPin, GPIO_PMD_OPEN_DRAIN);
  344.                                         P33=0;  //CECpin low, for ACK bit
  345.                                         CEC_SetTimer(3600); //force low time 3.4~3.8ms, ack bit timming error
  346.                                         //printf("bit timing error  \n");
  347.                     */
  348.                 }

  349.                 if (u8CECTimerCNT < 8)
  350.                 {
  351.                     if (P33 == 1)
  352.                         au8CECRxData[u8CECRxLength] |= 0x80 >> u8CECTimerCNT;      //get high CEC bit
  353.                     else
  354.                         au8CECRxData[u8CECRxLength] &= ~(0x80 >> u8CECTimerCNT);   //get low CEC bit

  355.                     u8CECTimerCNT++;

  356.                     NVIC_EnableIRQ(CECExtInt);  //enable ext int check
  357.                     u8CECEIntStatus = 0;      //check if the timer is trigged from ext int
  358.                     CEC_SetTimer(2000);
  359.                 }
  360.                 else if (u8CECTimerCNT == 8)  //EOM proc
  361.                 {
  362.                     if (P33 == 1) //check end of message
  363.                         u8CECEOM = 1;
  364.                     else
  365.                         u8CECEOM = 0;

  366.                     if (u8CECLogicalAddr == (au8CECRxData[0] & 0xf)) //check dest address, if equal, receiver will reply ACK
  367.                         u8CECReAckFlag = u8CECSubCNT = 1;    //flag for ACK
  368.                     else
  369.                         u8CECReAckFlag = u8CECSubCNT = 0;    //flag for NOACK

  370.                     u8CECTimerCNT = 9;
  371.                     NVIC_EnableIRQ(CECExtInt);  //enable ext int check
  372.                     u8CECEIntStatus = 0;      //check if the timer is trigged from ext int
  373.                     CEC_SetTimer(1000000);

  374.                     //printf("received:%d data:%d  \n",u8CECRxLength,au8CECRxData[u8CECRxLength]);
  375.                     u8CECRxLength++;
  376.                 }
  377.                 else if (u8CECTimerCNT == 9) //ACK process
  378.                 {
  379.                     if (u8CECSubCNT == 0)
  380.                     {
  381.                         if (u8CECEOM == 1)
  382.                         {
  383.                             u8CECGetData = 1; //receive finished

  384.                             if (u8CECTxLength)
  385.                             {
  386.                                 SendData(u8CECTxLength);  //goto transmit mode
  387.                                 CEC_SetTimer(10000);    //delay for safe, long delay for ACK bit finish
  388.                             }
  389.                             else
  390.                                 CECSetReceive();        //trun receive state

  391.                             //printf("Get data 1  \n");
  392.                         }
  393.                         else
  394.                         {
  395.                             NVIC_EnableIRQ(CECExtInt);  //enable ext int check
  396.                             u8CECEIntStatus = 0;      //check if the timer is trigged from ext int
  397.                             CEC_SetTimer(1000000);
  398.                             u8CECTimerCNT = u8CECSubCNT = 0; //keep receive other data
  399.                         }
  400.                     }
  401.                     else if (u8CECSubCNT == 1)
  402.                     {
  403.                         GPIO_SetMode(CECPort, CECPin, GPIO_PMD_OPEN_DRAIN);
  404.                         P33 = 0; //CECpin low, for ACK bit
  405.                         CEC_SetTimer(1400);     //ack low 1.5ms, after TCL test, this need set 1300
  406.                         u8CECEIntStatus = 0xff;
  407.                         u8CECSubCNT = 2;
  408.                     }
  409.                     else if (u8CECSubCNT == 2)
  410.                     {
  411.                         P33 = 1; //CECpin high, for ACK bit
  412.                         CEC_SetTimer(300);      //should be 900,but it will mask next falling edge, so set 300
  413.                         u8CECEIntStatus = 0xff;
  414.                         u8CECSubCNT = 3;
  415.                     }
  416.                     else if (u8CECSubCNT == 3)
  417.                     {
  418.                         //followed 2 line clear ACK high caused Ext pending int, must do!
  419.                         ClearExtInt();
  420.                         NVIC_ClearPendingIRQ(CECExtInt);
  421.                         GPIO_SetMode(CECPort, CECPin, GPIO_PMD_INPUT);

  422.                         if (u8CECEOM == 1)
  423.                         {
  424.                             u8CECGetData = 1; //receive finished

  425.                             if (u8CECTxLength)
  426.                             {
  427.                                 SendData(u8CECTxLength);  //goto transmit mode
  428.                                 CEC_SetTimer(7000); //delay for safe
  429.                             }
  430.                             else
  431.                                 CECSetReceive();

  432.                             //printf("Get data 2  \n");
  433.                         }
  434.                         else
  435.                         {
  436.                             NVIC_EnableIRQ(CECExtInt);  //enable ext int check
  437.                             u8CECEIntStatus = 0;      //check if the timer is trigged from ext int
  438.                             CEC_SetTimer(1000000);
  439.                             u8CECTimerCNT = u8CECSubCNT = 0; //keep receive other data
  440.                             //printf("keep receive  \n");
  441.                         }
  442.                     }

  443.                 }
  444.             }
  445.             break;

  446.             case    2:
  447.             {
  448.                 /*  printf("low level keeped 3.6ms  \n");
  449.                     ClearExtInt();
  450.                     NVIC_ClearPendingIRQ(CECExtInt);
  451.                     GPIO_SetMode(CECPort, CECPin, GPIO_PMD_INPUT);
  452.                     if(u8CECTxLength)
  453.                         {
  454.                         SendData(u8CECTxLength);  //go to transmit mode
  455.                         CEC_SetTimer(10000);    //delay for safe, long delay for ACK bit finish
  456.                         }
  457.                     else
  458.                         CECSetReceive();        //go to receive state
  459.                 */
  460.             }

  461.             default:
  462.                 break;

  463.         }
  464.     }
  465.     else if (u8CECTRStatus == CECIdle) // if transmit failed, it will goto receive mode, if there is not any siginal for a certain time,it will goto transmit mode again
  466.     {
  467.         if (u8CECTxLength > 0)
  468.             SendData(u8CECTxLength);  //goto transmit mode
  469.         else
  470.             CECSetReceive();        //go to receive state
  471.     }

  472.     return;
  473. }
















































































































 楼主| wanduzi 发表于 2024-2-25 19:47 | 显示全部楼层
  1. /**************************************************************************//**
  2. * @file     Smpl_CEC.h
  3. * @brief    M051 CEC driver header file
  4. *
  5. * @note
  6. * Copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
  7. *****************************************************************************/
  8. #include <stdio.h>
  9. #include <stdint.h>
  10. #include "M051Series.h"

  11. #ifndef __CEC_H__
  12. #define __CEC_H__


  13. void InitialCEC(void);      //initialize CEC used resource, inlcude: timer0, GPIO
  14. void CEC_TimerEvent(void);

  15. #define CECPort P3
  16. #define CECPin  3
  17. #define CECTimer    TIMER3
  18. #define CECExtInt   EINT1_IRQn

  19. //define CEC states
  20. #define CECIdle 0
  21. #define CECReceive  1
  22. #define CECtransmit 2

  23. //define flow control status
  24. #define CECNewSend      0
  25. #define CECPreSendFail  1


  26. #define CECMaxPayload       16
  27. extern uint8_t  au8CECTxData[CECMaxPayload], au8CECRxData[CECMaxPayload];
  28. //define
  29. //au8CECTxData[0]--header
  30. //au8CECTxData[1]--data1
  31. //...

  32. extern volatile uint8_t  u8CECTxLength;
  33. extern uint8_t  u8CECState, u8CECTRStatus, u8CECLogicalAddr, u8CECPhysicalAddr,
  34.        u8CECTxRemain, u8CECRxLength, u8CECEOM, u8CECGetData;

  35. extern uint8_t  u8CECEIntStatus, u8CECTimerCNT, u8CECRetranCNT, u8CECSubCNT, u8CECSrcAddr, u8CECDstAddr;
  36. extern uint8_t  u8CECErrorFlag, u8CECReAckFlag;

  37. extern uint16_t u16CECAckFlag, u16CECAckCheckFlag;
  38. //u16CECAckFlag define
  39. //#define   HeadAck 0x8000
  40. //#define   Data1Ack    0x4000
  41. //#define   Data2Ack    0x2000
  42. //#define   Data3Ack    0x1000
  43. //......
  44. //#define   Data15Ack   0x0001


  45. void CEC_SetTimer(uint32_t  us);

  46. void    ClearExtInt(void);


  47. void CECSetReceive(void);       //CEC initial receive mode

  48. void SendData(uint8_t   DataLength);

  49. #endif //__CEC_H__
  50. /*** (C) COPYRIGHT 2019 Nuvoton Technology Corp. ***/
 楼主| wanduzi 发表于 2024-2-25 19:47 | 显示全部楼层
此范例程序使用P3.3以及timer3实现CEC协议。用户可以在P3.3接上拉电阻再接到HDMI总线中的CEC控制线上,然后就可以发送命令到CEC总线上的其他设备,也可以接收其他设备发送的CEC命令,如果地址匹配MCU会自动回复应答信号给发送设备
 楼主| wanduzi 发表于 2024-2-25 19:48 | 显示全部楼层
CEC总线拥有类似I2C总线的仲裁功能,所以我们要将CEC管脚配置为开漏输出并且要接上拉电阻,这样才可以将MCU管脚接到HDMI总线的CEC控制线上
2177265db2902eb460.png
jiekou001 发表于 2024-2-26 17:19 | 显示全部楼层
CEC总线是做什么的?
jiekou001 发表于 2024-2-26 17:19 | 显示全部楼层
怎么看着像单线协议啊
jiekou001 发表于 2024-2-26 17:21 | 显示全部楼层
是这个吗?
CEC(Consumer Electronics Control)是一套完整的单总线协议,电子设备可以借着CEC信号让使用可控制HDMI接口上所连接的装置,比如单键播放(One Touth Play),系统待机(System Standby),可以实现由单一遥控器控制所有HDMI连接的装置。最多可以控制15个设备。允许HDMI设备在没有用户干扰情况下互相命令控制。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

156

主题

1882

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部