/* ********************************************************************************************************* * 函 数 名: DS18B20_ReadByte * 功能说明: 向DS18B20读取1字节数据 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static uint8_t DS18B20_ReadByte(void) { /* 写数据时序, 见DS18B20 page 16 */ uint8_t i; uint8_t read = 0; for (i = 0; i < 8; i++) { read >>= 1; DQ_0(); bsp_DelayUS(3); DQ_1(); bsp_DelayUS(3); if (DQ_IS_LOW()) { ; } else { read |= 0x80; } bsp_DelayUS(60); } return read; }
/* ********************************************************************************************************* * 函 数 名: DS18B20_WriteByte * 功能说明: 向DS18B20写入1字节数据 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static void DS18B20_WriteByte(uint8_t _val) { /* 写数据时序, 见DS18B20 page 16 */ uint8_t i; for (i = 0; i < 8; i++) { DQ_0(); bsp_DelayUS(2); if (_val & 0x01) { DQ_1(); } else { DQ_0(); } bsp_DelayUS(60); DQ_1(); bsp_DelayUS(2); _val >>= 1; } }
/********************************************************************** functionName: void i2c_send_notack(void) description:发送非应答 **********************************************************************/ void i2c_send_notack(void) { SET_SDA; bsp_DelayUS(I2C_DELAY); SET_SCL; bsp_DelayUS(I2C_DELAY); CLR_SCL; }
/********************************************************************** functionName:void i2_stop(void) description:I2C停止标志 **********************************************************************/ void i2_stop(void) { CLR_SCL; CLR_SDA; bsp_DelayUS(I2C_DELAY); SET_SCL; bsp_DelayUS(I2C_DELAY); SET_SDA; }
/********************************************************************** functionName:void i2_start(void) description:I2C开始标志 **********************************************************************/ void i2_start(void) { SET_SDA; SET_SCL; bsp_DelayUS(I2C_DELAY); CLR_SDA; bsp_DelayUS(I2C_DELAY); CLR_SCL; }
/********************************************************************** functionName:uint8_t i2c_wait_ack(void) description:I2C等待应答 **********************************************************************/ uint8_t i2c_wait_ack(void) { uint16_t errtime=2555;//因故障接收方无ACK,超时值为255。 i2c_slave(); bsp_DelayUS(I2C_DELAY); SET_SCL; bsp_DelayUS(I2C_DELAY); while(STU_I2C_SDA) { errtime--; if (!errtime) { i2_stop(); return 0x00; } } CLR_SCL; i2c_mastar(); return 0xff; }
/********************************************************************** functionName:uint8_t i2c_recv_byte(void) description:I2C接受字节 **********************************************************************/ uint8_t i2c_recv_byte(void) { uint8_t i=8; uint8_t ddata=0; i2c_slave(); while (i--) { ddata<<=1; CLR_SCL; bsp_DelayUS(I2C_DELAY); SET_SCL; bsp_DelayUS(I2C_DELAY); if(STU_I2C_SDA) ddata|=0x01; } CLR_SCL; i2c_mastar(); return ddata; }
/********************************************************************** functionName:void i2c_sendbyte(uint8_t temp) description:I2C发送字节 **********************************************************************/ void i2c_sendbyte(uint8_t temp) { uint8_t i=8; while (i--) { CLR_SCL; bsp_DelayUS(I2C_DELAY); if(temp&0x80) { SET_SDA; } else { CLR_SDA; } temp<<=1; bsp_DelayUS(I2C_DELAY); SET_SCL; bsp_DelayUS(I2C_DELAY); } CLR_SCL; }
/* ********************************************************************************************************* * 函 数 名: PS2_SendCmd * 功能说明: 向鼠标或键盘发送1字节数据 * 形 参: _byte : 待发送的数据 * 返 回 值: 无 ********************************************************************************************************* */ static void PS2_SendCmd(uint8_t _byte) { /* 主机必须按下面的步骤发送数据到PS/2设备: 1) 把Clock线拉低至少100us; 2) 把Data线拉低; 3) 释放Clock线; 4) 等待PS/2设备把Clock线拉低; 5) 设置/复位Data线发送第一个数据位; 6) 等待PS/2设备把时钟拉高; 7) 等待PS/2设备把时钟拉低; 8) 重复5-7步发送剩下的7个数据位和校验位; 9) 释放Data线,即发送停止位(1); 10) 等待PS/2设备把Clock线拉高; //此步可省略,因为下一步PS/2设备还是会把Data线拉低的 11) 等待PS/2设备把Data线拉低; 12) 等待PS/2设备把Clock线拉低; 13) 等待PS/2设备释放Clock线和Data线。 */ g_tPS2.Sending = 1; g_tPS2.Cmd = _byte; g_tPS2.Status = 0; /* */ PS2_CLK_0(); /* 把Clock线拉低至少100us --- 设置低后会触发CLK下降沿中断(中断服务程序应该丢弃这个事件) */ bsp_DelayUS(100); PS2_DATA_0(); /* 把Data线拉低 */ g_tPS2.TxTimeOut = 2; /* 避免没插PS2设备时,DATA线一直被拉低 */ bsp_DelayUS(50); PS2_CLK_1(); /* 释放Clock线 */ /* 后面的过程有CLK下降沿中断服务程序完成 */ }
/** * @brief USB_OTG_BSP_uDelay * This function provides delay time in micro sec * @param usec : Value of delay required in micro sec * @retval None */ void USB_OTG_BSP_uDelay (const uint32_t usec) { bsp_DelayUS(usec); // #ifdef USE_ACCURATE_TIME // BSP_Delay(usec,TIM_USEC_DELAY); // #else // __IO uint32_t count = 0; // const uint32_t utime = (120 * usec / 7); // do // { // if ( ++count > utime ) // { // return ; // } // } // while (1); // #endif }
/* ********************************************************************************************************* * 函 数 名: PS2_WaitMsg * 功能说明: 等待应答. * 形 参: _rsp : 存放结果 * _timeout : 超时时间,必须大于0。单位 ms * 返 回 值: 0 表示无数据, 1表示成功 ********************************************************************************************************* */ static uint8_t PS2_WaitMsg(uint32_t *_rsp, uint16_t _timeout) { uint32_t read; uint16_t i; for (i = 0; i < _timeout; i++) { read = PS2_GetMsg(); if (read != PS2_NONE) { *_rsp = read; break; } bsp_DelayUS(1000); } g_tPS2.Sending = 0; if (i == _timeout) { return 0; /* 超时未读到数据 */ } return 1; /* 成功读到数据 */ }
/** * @brief USB_OTG_BSP_uDelay * This function provides delay time in micro sec * @param usec : Value of delay required in micro sec * @retval None */ void USB_OTG_BSP_uDelay (const uint32_t usec) { bsp_DelayUS(usec); }
/* ********************************************************************************************************* * 函 数 名: DS18B20_Reset * 功能说明: 复位DS18B20。 拉低DQ为低,持续最少480us,然后等待 * 形 参: 无 * 返 回 值: 0 失败; 1 表示成功 ********************************************************************************************************* */ uint8_t DS18B20_Reset(void) { /* 复位时序, 见DS18B20 page 15 首先主机拉低DQ,持续最少 480us 然后释放DQ,等待DQ被上拉电阻拉高,约 15-60us DS18B20 将驱动DQ为低 60-240us, 这个信号叫 presence pulse (在位脉冲,表示DS18B20准备就绪 可以接受命令) 如果主机检测到这个低应答信号,表示DS18B20复位成功 */ uint8_t i; uint16_t k; DISABLE_INT();/* 禁止全局中断 */ /* 复位,如果失败则返回0 */ for (i = 0; i < 1; i++) { DQ_0(); /* 拉低DQ */ bsp_DelayUS(520); /* 延迟 520uS, 要求这个延迟大于 480us */ DQ_1(); /* 释放DQ */ bsp_DelayUS(15); /* 等待15us */ /* 检测DQ电平是否为低 */ for (k = 0; k < 10; k++) { if (DQ_IS_LOW()) { break; } bsp_DelayUS(10); /* 等待65us */ } if (k >= 10) { continue; /* 失败 */ } /* 等待DS18B20释放DQ */ for (k = 0; k < 30; k++) { if (!DQ_IS_LOW()) { break; } bsp_DelayUS(10); /* 等待65us */ } if (k >= 30) { continue; /* 失败 */ } break; } ENABLE_INT(); /* 使能全局中断 */ bsp_DelayUS(5); if (i >= 1) { return 0; } return 1; }
/* ********************************************************************************************************* * 函 数 名: RTC_Config * 功能说明: 用于配置时间戳功能 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void RTC_Config(void) { int RtcTimeout; /* RTC超时计数 */ RTC_TimeTypeDef RTC_TimeStructure; RTC_InitTypeDef RTC_InitStructure; RTC_DateTypeDef RTC_DateStructure; Mem_Set(&RTC_TimeStructure, 0x00, sizeof(RTC_TimeTypeDef)); Mem_Set(&RTC_InitStructure, 0x00, sizeof(RTC_InitTypeDef)); Mem_Set(&RTC_DateStructure, 0x00, sizeof(RTC_DateTypeDef)); RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);/* 使能PWR时钟 */ PWR_BackupAccessCmd(ENABLE);/* 允许访问RTC */ try_again: if(OBCBootInfo.BootRTC_Source == 0) /* 选择LSE作为时钟源 */ { RCC_LSEConfig(RCC_LSE_ON); /* 使能LSE振荡器 */ RtcTimeout = 0; /* 等待就绪 */ while((RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) && ((RtcTimeout++) < RTC_TIMEOUT_US))//20 { bsp_DelayUS(1); /* STM32延迟函数 */ } if(RtcTimeout > RTC_TIMEOUT_US) //18 /* 判断是否有超时 */ { DEBUG_LOG("Init RTC Wrong: Oscillator time out! \r\n"); RCC_LSEConfig(RCC_LSE_OFF); OBCBootInfo.BootLSE_Error = 1; OBCBootInfo.BootRTC_Source = 1; /* 自动配置RTC为内部时钟 */ } if(OBCBootInfo.BootRTC_Source == 0) { DEBUG_LOG("Enable RTC with LSE \r\n"); RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); /* 选择RTC时钟源 */ uwSynchPrediv = 0xFF; uwAsynchPrediv = 0x7F; } } if(OBCBootInfo.BootRTC_Source == 1) /* 选择LSI作为时钟源 */ { RCC_LSICmd(ENABLE); /* 使能内部时钟 */ RtcTimeout = 0; /* 等待内部时钟稳定*/ while((RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) && ((RtcTimeout++) < RTC_TIMEOUT_US)) { bsp_DelayUS(1); /* STM32延迟函数 */ } if(RtcTimeout > RTC_TIMEOUT_US) { DEBUG_LOG("All Oscillator time out! \r\n"); //RCC_LSICmd(DISABLE); OBCBootInfo.BootLSI_Error = 1; OBCBootInfo.BootRTC_Source = 2; /* 自动配置RTC为内部时钟 */ } if(OBCBootInfo.BootRTC_Source == 1) { DEBUG_LOG("Enable RTC with LSI \r\n"); RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); /* 选择RTC时钟源 */ uwSynchPrediv = 0xFF; uwAsynchPrediv = 0x7F; } } if((OBCBootInfo.BootRTC_Source == 0)||(OBCBootInfo.BootRTC_Source == 1)) { RCC_RTCCLKCmd(ENABLE); /* 使能RTC时钟 */ RTC_WaitForSynchro(); /* 等待RTC APB寄存器同步 */ RTC_TimeStampCmd(RTC_TimeStampEdge_Falling, ENABLE); /* 使能时间戳 */ RTC_TimeStampPinSelection(RTC_TamperPin_PC13); RTC_InitStructure.RTC_AsynchPrediv = uwAsynchPrediv; /* 配置RTC数据寄存器和分频器 */ RTC_InitStructure.RTC_SynchPrediv = uwSynchPrediv; RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24; if (RTC_Init(&RTC_InitStructure) == ERROR) /* 检测RTC初始化 */ { DEBUG_LOG("RTC Init wrong \r\n"); if(OBCBootInfo.BootRTC_Source == 0) { OBCBootInfo.BootRTC_Source = 1; goto try_again; } } /* 设置年月日和星期 */ RTC_DateStructure.RTC_Year = 0x14; RTC_DateStructure.RTC_Month = RTC_Month_October; RTC_DateStructure.RTC_Date = 0x23; RTC_DateStructure.RTC_WeekDay = RTC_Weekday_Thursday; RTC_SetDate(RTC_Format_BCD, &RTC_DateStructure); /* 设置时分秒,以及显示格式 */ RTC_TimeStructure.RTC_H12 = RTC_H12_AM; RTC_TimeStructure.RTC_Hours = 0x00; RTC_TimeStructure.RTC_Minutes = 0x00; RTC_TimeStructure.RTC_Seconds = 0x00; RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure); } }