#include "stm32f10x.h" #include "uart.h" #include "IrDA.h" #include "Mem.h" #include "debug_printf.h" #include "hal_radio.h" enum { IRDA_STATUS_NONE, IRDA_STATUS_TX, IRDA_STATUS_RX, IRDA_STATUS_RECEIVE, }; enum { END = 0, FINISH, WAIT, }; typedef struct { u8 fLen; u8 index; }IRDA_FLAG; enum { IRDA_ERR = 0x0000, IRDA_TX_START = 0x0001, IRDA_RX_START = 0x0002, IRDA_TX_FINISH = 0x0004, IRDA_RX_FINISH = 0x0008, IRDA_RX_ERR = 0x0010, IRDA_RX_WAIT = 0x0020, }; #define IRDA_TX_TIMEOUT 1000 #define IRDA_RX_TIMEOUT 1000 static IRDA_FLAG IRDA_TX_flag; u8 IRDA_TX_buf[IRDA_TX_BUFFER_SIZE]; static IRDA_FLAG IRDA_RX_flag; u8 IRDA_RX_buf[IRDA_RX_BUFFER_SIZE]; static u8 IRDA_status = IRDA_STATUS_NONE; TaskHandle_t IRDA_task_handle; /***************************************************************************** * Function : IRDA_RX_start * Description : none * Input : void * Output : None * Return : * Others : * Record * 1.Date : 20170515 * Author : barry * Modification: Created function *****************************************************************************/ void IRDA_RX_start(void) { IRDA_GPIO_RX_init(); IRDA_RX_flag.fLen = 0; IRDA_RX_flag.index = 0; IRDA_status = IRDA_STATUS_RX; } /***************************************************************************** * Function : IRDA_RX_stop * Description : none * Input : void * Output : None * Return : * Others : * Record * 1.Date : 20170515 * Author : barry * Modification: Created function *****************************************************************************/ void IRDA_RX_stop(void) { TIM_Cmd(IRDA_BAUD_TIMER, DISABLE); hal_sRF_FSK_ITConfig(IRDA_RX_LINE , DISABLE); GPIO_SetBits(IRDA_TX_PORT, IRDA_TX_PIN); IRDA_RX_flag.fLen = 0; IRDA_RX_flag.index = 0; } /***************************************************************************** * Function : IRDA_GPIO_RX_init * Description : none * Input : void * Output : None * Return : * Others : * Record * 1.Date : 20170515 * Author : barry * Modification: Created function *****************************************************************************/ void IRDA_GPIO_RX_init(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(IRDA_RX_PORT_CLK, ENABLE); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = IRDA_RX_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init( IRDA_RX_PORT, &GPIO_InitStructure ); EXTI_ClearITPendingBit(IRDA_RX_LINE); GPIO_EXTILineConfig(IRDA_RX_PORT_SOURCE, IRDA_RX_PIN_SOURCE); EXTI_InitStructure.EXTI_Line = IRDA_RX_LINE; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } /***************************************************************************** * Function : IRDA_GPIO_TX_init * Description : none * Input : void * Output : None * Return : * Others : * Record * 1.Date : 20170515 * Author : barry * Modification: Created function *****************************************************************************/ void IRDA_GPIO_TX_init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(IRDA_TX_PORT_CLK | RCC_APB2Periph_AFIO, ENABLE); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = IRDA_TX_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_Init( IRDA_TX_PORT, &GPIO_InitStructure ); GPIO_SetBits(IRDA_TX_PORT, IRDA_TX_PIN); } /***************************************************************************** * Function : GPIO_TX_high * Description : 发送高电平时无需加载载波,开始时已经启动定时器 * Input : void * Output : None * Return : * Others : * Record * 1.Date : 20170515 * Author : barry * Modification: Created function *****************************************************************************/ void GPIO_TX_high(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_Cmd(PWM_TIMER, DISABLE); GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = IRDA_TX_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_Init( IRDA_TX_PORT, &GPIO_InitStructure ); GPIO_SetBits(IRDA_TX_PORT, IRDA_TX_PIN); } /***************************************************************************** * Function : GPIO_TX_low * Description : IRDA发送时,低电平需要加载载波信号 * Input : void * Output : None * Return : * Others : * Record * 1.Date : 20170515 * Author : barry * Modification: Created function *****************************************************************************/ void GPIO_TX_low(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; IRDA_GPIO_TX_init(); RCC_APB1PeriphClockCmd(PWM_TIMER_CLK, ENABLE); //时钟使能 TIM_TimeBaseStructure.TIM_Period = PWM_PERIOD; // period TIM_TimeBaseStructure.TIM_Prescaler = PWM_PRESC; // 时钟分频 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(PWM_TIMER, &TIM_TimeBaseStructure); //初始化TIM2 Channel1 PWM模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高 TIM_OCInitStructure.TIM_Pulse = PWM_PERIOD / 2; TIM_OC1Init(PWM_TIMER, &TIM_OCInitStructure); TIM_OC2PreloadConfig(PWM_TIMER, TIM_OCPreload_Enable); //使能在CCR2上的预装载寄存器 TIM_CtrlPWMOutputs(PWM_TIMER, ENABLE); TIM_Cmd(PWM_TIMER, ENABLE); } /***************************************************************************** * Function : baud_timer_init * Description : none * Input : u32 preriod * Output : None * Return : * Others : * Record * 1.Date : 20170515 * Author : barry * Modification: Created function *****************************************************************************/ void baud_timer_init(u32 preriod) { RCC_APB1PeriphClockCmd(IRDA_BAUD_TIMER_CLK, ENABLE); TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; TIM_TimeBaseStructure.TIM_Period = preriod; // period TIM_TimeBaseStructure.TIM_Prescaler = IRDA_BAUD_PRESC; // 时钟分频 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(IRDA_BAUD_TIMER, &TIM_TimeBaseStructure); NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_ClearFlag(IRDA_BAUD_TIMER, TIM_FLAG_Update); TIM_ITConfig(IRDA_BAUD_TIMER, TIM_IT_Update, ENABLE); //允许更新中断 TIM_Cmd(IRDA_BAUD_TIMER, ENABLE); } /***************************************************************************** * Function : IRDA_TX_bit * Description : none * Input : u8 bitVal * Output : None * Return : * Others : * Record * 1.Date : 20170515 * Author : barry * Modification: Created function *****************************************************************************/ void IRDA_TX_bit(u8 bitVal) { if (bitVal == 0) { GPIO_TX_low(); } else { GPIO_TX_high(); } } /***************************************************************************** * Function : IRDA_TX * Description : none * Input : u8 *buf u8 length * Output : None * Return : * Others : * Record * 1.Date : 20170515 * Author : barry * Modification: Created function *****************************************************************************/ void IRDA_TX(u8 *buf, u8 length) { IRDA_RX_stop(); IRDA_TX_flag.fLen = length; IRDA_TX_flag.index = 0; if ((IRDA_status != IRDA_STATUS_RECEIVE) || (IRDA_status != IRDA_STATUS_TX)) { IRDA_GPIO_TX_init(); IRDA_status = IRDA_STATUS_TX ; MemCpy(IRDA_TX_buf, buf, length); hal_sRF_FSK_ITConfig(IRDA_RX_LINE , DISABLE); TIM_ClearITPendingBit(IRDA_BAUD_TIMER, TIM_IT_Update); baud_timer_init(IRDA_BAUD_PERIOD); xTaskNotify(IRDA_task_handle, IRDA_TX_START, eSetBits); printf("IRDA start tx\r\n"); } else { printf("IRDA tx when rx\r\n"); } } /***************************************************************************** * Function : IRDA_task * Description : none * Input : void *ptr * Output : None * Return : * Others : * Record * 1.Date : 20170515 * Author : barry * Modification: Created function *****************************************************************************/ void IRDA_task(void *ptr) { TickType_t xTicksToWait; TimeOut_t xTimeOut; IRDA_GPIO_RX_init(); IRDA_GPIO_TX_init(); //IRDA_RX_start(); for (;;) { uint32_t notifyValue = 0; xTaskNotifyWait(0xFF, 0xFF, ¬ifyValue, portMAX_DELAY); if (notifyValue == IRDA_TX_START) { xTicksToWait = IRDA_TX_TIMEOUT / portTICK_RATE_MS; vTaskSetTimeOutState(&xTimeOut); while(1) { if (xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE) { xTaskNotifyWait(0xFF, 0xFF, ¬ifyValue, xTicksToWait); if (notifyValue == IRDA_TX_FINISH) { printf("IRDA tx finish\r\n"); break; } } else { printf("IRDA tx timeout\r\n"); break; } } IRDA_RX_start(); } else if (notifyValue == IRDA_RX_START) { xTicksToWait = IRDA_RX_TIMEOUT / portTICK_RATE_MS; vTaskSetTimeOutState(&xTimeOut); while(1) { if (xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE) { xTaskNotifyWait(0xFF, 0xFF, ¬ifyValue, xTicksToWait); if (notifyValue == IRDA_RX_FINISH) { break; } else if (notifyValue == IRDA_RX_ERR) { break; } } else { break; } } IRDA_RX_start(); } } } /***************************************************************************** * Function : create_IRDA_task * Description : none * Input : void * Output : None * Return : * Others : * Record * 1.Date : 20170515 * Author : barry * Modification: Created function *****************************************************************************/ void create_IRDA_task(void) { xTaskCreate(IRDA_task, NULL, 100, NULL, 2, &IRDA_task_handle); } /***************************************************************************** Prototype : DLT645_protocol_receive Description : Input : Output : None Return Value : Date : 2014/3/15 Author : Barry *****************************************************************************/ u32 DLT645_protocol_receive(u8 * rxBuf, IRDA_FLAG * rx_flag) { u32 status = IRDA_RX_WAIT; switch(rx_flag->index) { case 0: if(rxBuf[rx_flag->index] != 0x68) { rx_flag->index = 0; status = IRDA_RX_ERR; } else { rx_flag->index++; } break; case 9: rx_flag->fLen = rxBuf[rx_flag->index] + 12; rx_flag->index++; break; default: rx_flag->index++; if (rx_flag->index > 9) { if ( rx_flag->index == rx_flag->fLen ) { if ( (rxBuf[rx_flag->index - 1] == 0x16) && (rxBuf[rx_flag->index -2] == GetSum(rxBuf, rx_flag->fLen - 2))) { status = IRDA_RX_FINISH; rx_flag->index = 0; } else { status = IRDA_RX_ERR; rx_flag->index = 0; } } } break; } return status; } /***************************************************************************** * Function : IRDA_BAUD_IRQHandler * Description : none * Input : void * Output : None * Return : * Others : * Record * 1.Date : 20170515 * Author : barry * Modification: Created function *****************************************************************************/ void IRDA_BAUD_IRQHandler(void) { u8 start_bit = 0; u8 end_bit = 1; u8 check_bit; static u8 rxByte = 0; static u8 tx_bit_pos = 0; static u8 rx_bit_pos = 0; BaseType_t pxHigherPriorityTaskWoken = pdFALSE; u8 status; if (TIM_GetITStatus(IRDA_BAUD_TIMER, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(IRDA_BAUD_TIMER, TIM_IT_Update); if (IRDA_status == IRDA_STATUS_TX) { switch (tx_bit_pos) { case 0: if (IRDA_TX_flag.index >= IRDA_TX_flag.fLen) { TIM_Cmd(IRDA_BAUD_TIMER, DISABLE); IRDA_status = IRDA_STATUS_NONE; xTaskNotifyFromISR(IRDA_task_handle, IRDA_TX_FINISH, eSetBits, &pxHigherPriorityTaskWoken); } else { IRDA_TX_bit( start_bit ); } tx_bit_pos++; break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: IRDA_TX_bit( (IRDA_TX_buf[IRDA_TX_flag.index] >> (tx_bit_pos - 1)) & 0x01); tx_bit_pos++; break; case 9: check_bit = 0; for (u8 i = 0; i < 8; i++) { check_bit += ((IRDA_TX_buf[IRDA_TX_flag.index] >> i) & 0x01); } check_bit = check_bit % 2; IRDA_TX_bit(check_bit); tx_bit_pos++; break; case 10: IRDA_TX_bit(end_bit); IRDA_TX_flag.index++; tx_bit_pos = 0; break; default: break; } } else if (IRDA_status == IRDA_STATUS_RECEIVE) { switch(rx_bit_pos) { case 0: if (IRDA_RX_BIT_VAL == 0) { baud_timer_init(IRDA_BAUD_PERIOD); rxByte = 0; rx_bit_pos++; } else { TIM_Cmd(IRDA_BAUD_TIMER, DISABLE); hal_sRF_FSK_ITConfig(IRDA_RX_LINE , ENABLE); IRDA_RX_start(); } break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: rxByte += IRDA_RX_BIT_VAL << (rx_bit_pos - 1); rx_bit_pos++; break; case 9: check_bit = 0; for (u8 i = 0; i < 8; i++) { check_bit += ((rxByte >> i) & 0x01); } check_bit = check_bit % 2; if (IRDA_RX_BIT_VAL != check_bit) { rx_bit_pos = 0; IRDA_RX_flag.index = 0; TIM_Cmd(IRDA_BAUD_TIMER, DISABLE); hal_sRF_FSK_ITConfig(IRDA_RX_LINE , ENABLE); } else { rx_bit_pos++; } break; case 10: rx_bit_pos = 0; if (IRDA_RX_BIT_VAL == 1)//停止位正确 { if (IRDA_RX_flag.index >= IRDA_RX_BUFFER_SIZE) { IRDA_RX_flag.index = 0; } IRDA_RX_buf[IRDA_RX_flag.index++] = rxByte; if (IRDA_RX_flag.index == 1) { xTaskNotifyFromISR(IRDA_task_handle, IRDA_RX_START, eSetBits, &pxHigherPriorityTaskWoken); } status = DLT645_protocol_receive(IRDA_RX_buf, &IRDA_RX_flag); if (status == IRDA_RX_WAIT) { TIM_Cmd(IRDA_BAUD_TIMER, DISABLE); hal_sRF_FSK_ITConfig(IRDA_RX_LINE , ENABLE); } else { IRDA_status = IRDA_STATUS_NONE; IRDA_RX_flag.index = 0; TIM_Cmd(IRDA_BAUD_TIMER, DISABLE); xTaskNotifyFromISR(IRDA_task_handle, status, eSetBits, &pxHigherPriorityTaskWoken); } } else //停止位错误 { IRDA_status = IRDA_STATUS_NONE; IRDA_RX_flag.index = 0; TIM_Cmd(IRDA_BAUD_TIMER, DISABLE); xTaskNotifyFromISR(IRDA_task_handle, IRDA_RX_ERR, eSetBits, &pxHigherPriorityTaskWoken); } break; } } } } /***************************************************************************** * Function : RX_START_IRQHandler * Description : none * Input : void * Output : None * Return : * Others : * Record * 1.Date : 20170515 * Author : barry * Modification: Created function *****************************************************************************/ void RX_START_IRQHandler(void) { if(EXTI_GetITStatus(IRDA_RX_LINE) != RESET) { EXTI_ClearITPendingBit(IRDA_RX_LINE); if ((IRDA_status == IRDA_STATUS_RX) || (IRDA_status == IRDA_STATUS_RECEIVE)) { IRDA_status = IRDA_STATUS_RECEIVE; hal_sRF_FSK_ITConfig(IRDA_RX_LINE , DISABLE); baud_timer_init(IRDA_BAUD_PERIOD/2); } } }