Files
2025-12-15 16:07:49 +08:00

725 lines
20 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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, &notifyValue, 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, &notifyValue, 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, &notifyValue, 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);
}
}
}