手机背夹设计

来源:互联网 发布:网络接入控制系统 编辑:程序博客网 时间:2024/05/16 01:10

手机背夹设计

一、整体概念设计

    为手机设计的一种背夹,具有OTG功能、hub和充电功能功能。具体如下:

    1、只插入手机时,手机处于host状态,充电宝给手机充电,同时手机可以访问充电宝上的SD卡

    2、插入电脑后,电脑处于host状态,手机和sd都是slave状态

    3、充电宝上有4个led,显示电量

    4、手机通过PD与充电宝进行通信与交互


    硬件芯片:STM32F030C8T6

    开发环境:windows xp/win7

    开发工具:IAR+STM32CUBEMX+ST_LINKER


二、各个模块设计

    主要包括了充电、放电、主从切换以及PD通信等主要的4个模块。下面从每个模块说起


1、充电模块

    这里充电采用的IC是BQ25895,带BC1.2协议的芯片,充电部分主要模仿MTK平台上的switch charging,具体driver code 如下:

#include "stm32f0xx_hal.h"#include "switch_charging.h"extern int8_t UI_Percentage;uint8_t charging_state=CHR_PRE;extern uint8_t charger_type;int16_t temp_input_cc_value;int16_t temp_cc_value;static void select_charging_current(){switch (charger_type){case STANDARD_HOST: //sdp usb host for max 500matemp_input_cc_value=500;temp_cc_value=500;break;case CHARGING_HOST: //cdp for max 1.5atemp_input_cc_value=1500;temp_cc_value=1500;break;case STANDARD_CHARGER: //dcp for max3.25atemp_input_cc_value=3000;temp_cc_value=3000;break;case UNKNOWN_CHARGER: //500matemp_input_cc_value=500;temp_cc_value=500;break;case NON_STANDARD_CHARGER: //appale charger 1atemp_input_cc_value=1000;temp_cc_value=1000;break;case NO_CHARGER:break;}}void pchr_turn_on_charging(){/***1:gpio enable***/HAL_GPIO_WritePin(GPIOA, GPIO_CHG_EN_Pin, GPIO_PIN_RESET);/***gpio enable***//***2:bq24595 reg init for charging***//***bq24595 reg init for charging***//***3:select charging current***/select_charging_current();bq2589x_set_input_current_limit(temp_input_cc_value);bq2589x_set_chargecurrent(temp_cc_value);/***select charging current***//***4:set cc_cv voltage***//***set cc_cv voltage***//***5:enable charging***/bq2589x_enable_charge();/****enable charging***/}static uint8_t charging_full_check(){uint8_t state;state=bq2589x_is_charge_done();return state;}void Pre_Charge_Mode(){pchr_turn_on_charging();if(UI_Percentage==100)charging_state=CHR_FULL;else charging_state=CHR_CC;}void Constant_Charge_Mode(){pchr_turn_on_charging();if(charging_full_check()==TRUE)charging_state=CHR_FULL;}void Battery_Full(){if(charging_full_check()==FALSE)charging_state=CHR_CC;}void mt_battery_charging_algorithm(void)//just like the mtk switch charging.{switch (charging_state){case CHR_PRE:Pre_Charge_Mode();break;case CHR_CC:Constant_Charge_Mode();break;case CHR_FULL:Battery_Full();break;default:break;}}

2、放电模块

    放电模块模仿的是展讯平台的,由于系统不带有硬件库仑计,只能采用通过读取电池的电压来换算成电池电量。 这里需要注意以下几点:

(1)、电池电量的变化不能出现跳变,充电时逐渐+1,放电时逐渐-1,

(2)、充电时电量只能增加,放电时只能减少


#include "stm32f0xx_hal.h"#include "battery_common.h"int8_t UI_Percentage;uint8_t chr_det=FALSE;uint8_t charger_type;uint8_t usb_typec_plug_in;uint8_t battery_run_timer=FALSE;uint8_t phone_is_online = FALSE;uint8_t pc_is_online =FALSE;uint8_t charger_is_online = FALSE;extern uint8_t charging_state;extern uint8_t sleep_mode;uint8_t need_init;/* usb mode select */void Usb_Sel_Host(enum host_is host_type){    if(host_type==PC){HAL_GPIO_WritePin(GPIOA, USB_SEL_Pin, GPIO_PIN_SET);}else if(host_type==PHONE){HAL_GPIO_WritePin(GPIOA, USB_SEL_Pin, GPIO_PIN_RESET);}else if(host_type==NONE){}}void check_host_is(){if(pc_is_online==TRUE && phone_is_online==TRUE){Usb_Sel_Host(PC);}else if(pc_is_online==TRUE && phone_is_online==FALSE){Usb_Sel_Host(PC);}else if(pc_is_online==FALSE && phone_is_online==TRUE){Usb_Sel_Host(PHONE);}else if(pc_is_online==FALSE && phone_is_online==FALSE){Usb_Sel_Host(NONE);}}/* interrupt for EINT_CHR_STAT callback */void check_chrdet_type(){uint8_t temp_charger_type;temp_charger_type=bq2589x_read_vbus_type();if(temp_charger_type==0)charger_type=NO_CHARGER;else if(temp_charger_type==1)charger_type=STANDARD_HOST;else if(temp_charger_type==2)charger_type=CHARGING_HOST;else if(temp_charger_type==3)charger_type=STANDARD_CHARGER;else if(temp_charger_type==5)charger_type=UNKNOWN_CHARGER;else if(temp_charger_type==6)charger_type=NON_STANDARD_CHARGER;if(temp_charger_type!=0 || temp_charger_type!=7)//0:no charger,7:OTG{charger_is_online= TRUE;chr_det = TRUE;}else{charger_is_online= FALSE;chr_det = FALSE;}}void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){if(GPIO_Pin==EINT_CHG_STAT_Pin){check_chrdet_type();if(charger_type==STANDARD_HOST || charger_type==CHARGING_HOST)pc_is_online = TRUE;elsepc_is_online = FALSE;}else if(GPIO_Pin==CC_INT_Pin){if(usb_typec_plug_in==TRUE){phone_is_online = TRUE;}else if(usb_typec_plug_in==FALSE){phone_is_online = FALSE;}}else if(GPIO_Pin==POWER_ON_N_Pin){if(sleep_mode==0)enter_stopmode();}check_host_is();if(sleep_mode==1){need_init=1;sleep_mode =0;}}static void sync_UI_percentage(){uint8_t percentage_temp;uint8_t timer=0;percentage_temp = get_battery_percentage();if(chr_det==TRUE){if(UI_Percentage<percentage_temp)timer++;else timer=0;if(timer==5)UI_Percentage++;if(UI_Percentage>100)UI_Percentage=100;}else if(chr_det==FALSE){if(UI_Percentage>percentage_temp)timer++;else timer=0;if(timer==5)UI_Percentage--;if(UI_Percentage<0)UI_Percentage=0;}}/***                      O ON  X OFF  * BLINK discharing:   0%~25% O X X X          25%~50% O O X X  50%~75% O O O X 75%~100% O O O O  charging: 0%~25% O * X X          25%~50% O O * X  50%~75% O O O * 75%~100% O O O O***/static void percentage_display(){sync_UI_percentage();if(chr_det==TRUE)//for charging{if(UI_Percentage>=75){Led_Sink_Set(LED_SINK_1,LED_ON);Led_Sink_Set(LED_SINK_2,LED_ON);Led_Sink_Set(LED_SINK_3,LED_ON);Led_Sink_Set(LED_SINK_4,LED_ON);}else if(UI_Percentage>=50){Led_Sink_Set(LED_SINK_1,LED_ON);Led_Sink_Set(LED_SINK_2,LED_ON);Led_Sink_Set(LED_SINK_3,LED_ON);Led_Sink_Blink(LED_SINK_4,LED_BLINK_TIME_1000);}else if(UI_Percentage>=25){Led_Sink_Set(LED_SINK_1,LED_ON);Led_Sink_Set(LED_SINK_2,LED_ON);Led_Sink_Blink(LED_SINK_3,LED_BLINK_TIME_1000);Led_Sink_Set(LED_SINK_4,LED_OFF);}else if(UI_Percentage>0){Led_Sink_Set(LED_SINK_1,LED_ON);Led_Sink_Blink(LED_SINK_2,LED_BLINK_TIME_1000);Led_Sink_Set(LED_SINK_3,LED_OFF);Led_Sink_Set(LED_SINK_4,LED_OFF);}}else if(chr_det==FALSE)//for dis_charging{if(UI_Percentage>=75){Led_Sink_Set(LED_SINK_1,LED_ON);Led_Sink_Set(LED_SINK_2,LED_ON);Led_Sink_Set(LED_SINK_3,LED_ON);Led_Sink_Set(LED_SINK_4,LED_ON);}else if(UI_Percentage>=50){Led_Sink_Set(LED_SINK_1,LED_ON);Led_Sink_Set(LED_SINK_2,LED_ON);Led_Sink_Set(LED_SINK_3,LED_ON);Led_Sink_Set(LED_SINK_4,LED_OFF);}else if(UI_Percentage>=25){Led_Sink_Set(LED_SINK_1,LED_ON);Led_Sink_Set(LED_SINK_2,LED_ON);Led_Sink_Set(LED_SINK_3,LED_OFF);Led_Sink_Set(LED_SINK_4,LED_OFF);}else if(UI_Percentage>0){Led_Sink_Set(LED_SINK_1,LED_ON);Led_Sink_Set(LED_SINK_2,LED_OFF);Led_Sink_Set(LED_SINK_3,LED_OFF);Led_Sink_Set(LED_SINK_4,LED_OFF);}}}uint8_t sleep_timer=0;void check_need_sleep(){if(phone_is_online==FALSE && pc_is_online==FALSE && charger_is_online ==FALSE)sleep_timer++;else sleep_timer =0;if(sleep_timer==6)//about 60 seconds.{enter_stopmode();//go to sleep modesleep_timer = 0;}}void battery_thread(){uart_printf("battery_thread:battery_run_timer=%d\n",battery_run_timer);if(battery_run_timer==TRUE){percentage_display();if(chr_det==TRUE){mt_battery_charging_algorithm();}else{charging_state = CHR_PRE;}check_need_sleep();}}/* get battery voltage adc value */void init_battery(){/***[1] init ui_percentage***/percentage_display();/***[2] check pc or phone is online or outline***/}

3、显示模块

    这里主要指的是4个led,4个led代表了电池的电量,主要就是实现了闪烁和亮灭,其驱动如下:

#include "stm32f0xx_hal.h"#include "led.h"//#include "stm32f0xx_it.h"static uint16_t blink_led_type=1;extern TIM_HandleTypeDef htim6;extern TIM_HandleTypeDef htim14;extern uint8_t battery_run_timer;/* interrupt for timer6 callback*/void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){if(htim->Instance==htim6.Instance){if((blink_led_type==LED_SINK_1_Pin) || (blink_led_type==LED_SINK_2_Pin))HAL_GPIO_TogglePin(GPIOF, blink_led_type);else if((blink_led_type==LED_SINK_3_Pin) || (blink_led_type==LED_SINK_4_Pin))HAL_GPIO_TogglePin(GPIOA, blink_led_type);}if(htim->Instance==htim14.Instance){battery_run_timer = TRUE;}}/* led set */void Led_Sink_Set(enum tct_led_sink_type led_type,enum tct_led_state led_state){    switch (led_type){case LED_SINK_1:if(led_state==LED_ON)HAL_GPIO_WritePin(GPIOF, LED_SINK_1_Pin, GPIO_PIN_SET);else HAL_GPIO_WritePin(GPIOF, LED_SINK_1_Pin, GPIO_PIN_RESET);break;case LED_SINK_2:if(led_state==LED_ON)HAL_GPIO_WritePin(GPIOF, LED_SINK_2_Pin, GPIO_PIN_SET);elseHAL_GPIO_WritePin(GPIOF, LED_SINK_2_Pin, GPIO_PIN_RESET);break;case LED_SINK_3:if(led_state==LED_ON)HAL_GPIO_WritePin(GPIOA, LED_SINK_3_Pin, GPIO_PIN_SET);elseHAL_GPIO_WritePin(GPIOA, LED_SINK_3_Pin, GPIO_PIN_RESET);break;case LED_SINK_4:if(led_state==LED_ON)HAL_GPIO_WritePin(GPIOA, LED_SINK_4_Pin, GPIO_PIN_SET);elseHAL_GPIO_WritePin(GPIOA, LED_SINK_4_Pin, GPIO_PIN_RESET);break;default:break;}}/* led blink */void Led_Sink_Blink(enum tct_led_sink_type led_type,enum tct_led_blink_time led_blink_time){if(led_blink_time==LED_BLINK_TIME_0)HAL_TIM_Base_Stop_IT(&htim6);//stop timer6else{htim6.Init.Prescaler = 0;//prescaler clockhtim6.Init.CounterMode = TIM_COUNTERMODE_UP;htim6.Init.Period = led_blink_time;//blink periodHAL_TIM_Base_Start_IT(&htim6);//start timer6}switch (led_type){case LED_SINK_1:blink_led_type=LED_SINK_1_Pin;break;case LED_SINK_2:blink_led_type=LED_SINK_2_Pin;break;case LED_SINK_3:blink_led_type=LED_SINK_3_Pin;break;case LED_SINK_4:blink_led_type=LED_SINK_4_Pin;break;default:break;}}/* led init */

4、调试模块

    这里主要采用UART口进行打印调试,因此要在UART上实现类似c语言中的printf函数

#include <stdio.h>#include <stdarg.h>#include "stm32f0xx_hal.h"#include "print.h"extern UART_HandleTypeDef huart1;void uart_printf(char *fmt, ...){char      uart1_pString[101]; va_list   uart1_ap;va_start(uart1_ap, fmt); vsnprintf(uart1_pString, 100, fmt, uart1_ap);va_end(uart1_ap);HAL_UART_Transmit_IT(&huart1, (uint8_t *)uart1_pString, sizeof(uart1_pString));}


4、睡眠模块

    单充电宝不使用时,系统需要进入待机模式,达到省电状态,stm32f0主要包括了三种省电状态

#include "stm32f0xx_hal.h"#include "sleep.h"uint8_t sleep_mode;void enter_stopmode(){sleep_mode =1;HAL_GPIO_WritePin(GPIOA, VDD33_HUB_EN_Pin, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOA, VDD33_EN_Pin, GPIO_PIN_RESET);HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);}


由于项目暂停,PD状态机的移植代码还没提供,因此没有继续开发下去,板子也没到,因此也没有在真实的板子上运行过,还有待验证。


0 0