<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 設(shè)計(jì)應(yīng)用 > 基于TI MSPM0L1306芯片的共享充電寶系統(tǒng)設(shè)計(jì)

          基于TI MSPM0L1306芯片的共享充電寶系統(tǒng)設(shè)計(jì)

          作者:鄭思源 時(shí)間:2025-01-20 來源:EEPW 收藏

          1   作者介紹

          本文引用地址:http://www.ex-cimer.com/article/202501/466479.htm

          我來自北京,碩士研究生,中級嵌入式工程師職稱。畢業(yè)后一直從事嵌入式開發(fā)領(lǐng)域工作,涉及工業(yè)控制,網(wǎng)絡(luò)通訊,人機(jī)界面等項(xiàng)目。雖多年工作經(jīng)驗(yàn),仍然熱愛著嵌入式開發(fā),也擁抱開源,樂于分享。

          2   項(xiàng)目概要

          本次設(shè)計(jì)是在做項(xiàng)目選型時(shí)了解到TI 公司MSPM0L1306 芯片非常適合做為共享充電寶等小設(shè)備的主控芯片。于是,計(jì)劃使用MSPM0L1306 復(fù)刻共享充電寶系統(tǒng)。共享充電寶系統(tǒng)主要有兩個(gè)核心功能:一、充電、放電控制,包含PD協(xié)議;二、管理與計(jì)費(fèi);還有輔助功能:充、放電監(jiān)測與保護(hù)功能;數(shù)據(jù)加密,解密與日志記錄功能等。

          在本次原型設(shè)計(jì)中,我們將利用MSPM0L1306 的特性來快速、簡潔的實(shí)現(xiàn)上述功能。

          3   系統(tǒng)架構(gòu)圖

          1737353084698247.png

          4   功能特性

          TI 公司的MSPM0L1306 芯片有著豐富的外設(shè),其中優(yōu)秀的數(shù)字通訊外設(shè)非常適合我們與外設(shè)器件進(jìn)行數(shù)據(jù)交互,而強(qiáng)大的模擬外設(shè)不僅讓我們的PCB 設(shè)計(jì)簡單,也提高了應(yīng)用的靈活性。下面我們簡單列出我們本次實(shí)現(xiàn)的主要功能,再重點(diǎn)講述一下,我們利用MSPM0L1306 芯片實(shí)現(xiàn)的高階應(yīng)用。

          4.1 系統(tǒng)時(shí)鐘

          在本次項(xiàng)目設(shè)計(jì)中,我們考慮到共享充電寶是基于電池設(shè)備的原因,所以我們盡量降低MCU 的運(yùn)行功耗。因此,我們將MSPM0L1306 的運(yùn)行主頻設(shè)定為4MHz,并使用內(nèi)部OSC 以減少功耗及BOM 成本。

          4.2 Uart串口

          我們使用Uart 串口做為我們調(diào)試輸出口,在調(diào)試階段打印輸出系統(tǒng)狀態(tài),以便我們分析,了解程序運(yùn)行狀態(tài)。在本次項(xiàng)目設(shè)計(jì)中,我們使用“9600-8-N-1”的串口配置參數(shù)。

          4.3 Timer外設(shè)的PWM模式

          為節(jié)省共享充電寶的LED 顯示燈的數(shù)量,我們利用PWM 波調(diào)節(jié)LED 的狀態(tài),以便顯示更多的狀態(tài)給用戶,增加用戶體驗(yàn)。即,在亮、滅兩種狀態(tài)下,增加呼吸燈狀態(tài),以示當(dāng)前在充、放電狀態(tài)。

          4.4 RTC實(shí)時(shí)時(shí)鐘

          共享充電寶需要有時(shí)基來計(jì)量當(dāng)前使用時(shí)間,充電時(shí)間,放電時(shí)間等參數(shù)。我們在MSPM0L1306 芯片上使能LFOSC,其將產(chǎn)生32.768KHz 的時(shí)鐘源激勵(lì)RTC實(shí)時(shí)時(shí)鐘。

          4.5 CRC校驗(yàn)

          CRC 校驗(yàn)算法,其在數(shù)據(jù)完整性檢查方面是最廣泛的應(yīng)用。部署CRC 算法的實(shí)現(xiàn)幾乎成為數(shù)據(jù)通訊的必選項(xiàng),而在MSPM0L1306 芯片內(nèi),已經(jīng)集成了CRC16和CRC32 兩種硬件算法,可以省去我們軟件實(shí)現(xiàn),釋放部分算力與代碼空間。

          4.6 AES加密解密算法

          在共享充電寶系統(tǒng)中,計(jì)費(fèi)系統(tǒng)是關(guān)鍵,也是非常重要的一環(huán)。計(jì)費(fèi)失敗導(dǎo)致的問題這里不多說,但每一個(gè)都“致命”級別的問題。而保障計(jì)費(fèi)安全的一個(gè)有力措施就是對數(shù)據(jù)進(jìn)行加密處理。復(fù)雜的AES 算法由MSPM0L1306的硬件模塊來實(shí)現(xiàn),將使得加密不再復(fù)雜,不再影響系統(tǒng)性能。

          4.7 NVM模塊

          每個(gè)產(chǎn)品都要有一個(gè)唯一的產(chǎn)品序列號,我們共享充電寶亦如此。不再程序開發(fā)階段寫入的序列號,也就只能在出廠前寫入。此時(shí)NVM 模塊便起到關(guān)鍵作用。我們也借助NVM 模塊,通過串口通道,將序列號寫入產(chǎn)品中。

          4.8 I2C通訊

          I2C 通訊是一個(gè)低成本,低速率的通訊協(xié)議。其使用2 線制即可傳輸數(shù)據(jù),主要應(yīng)用于板上通訊。在我們本次設(shè)計(jì)系統(tǒng)里面,我們主控芯片MSPM0L1306 做主設(shè)備通過I2C 外設(shè)與PD 充放電模塊從設(shè)備進(jìn)行數(shù)據(jù)交互,獲取當(dāng)前充電、放電的狀態(tài),從而進(jìn)行計(jì)費(fèi)與統(tǒng)計(jì)功能。我們的I2C 外設(shè)配置速率為100Kbps。

          4.9 I2C-SMBus通訊

          SMBus 協(xié)議是I2C 協(xié)議的一個(gè)子集。其使用I2C 協(xié)議,但在其之上又進(jìn)行了一層上層應(yīng)用層的封裝,可謂“青出于藍(lán),而勝于藍(lán)”。

          在本項(xiàng)目中的共享充電寶來說,其可以選擇任意一個(gè)充電站,選擇任意一個(gè)充電槽。所以,共享充電寶不可能以固定從地址的方式來接入充電站。這時(shí),低成本的I2C 總線協(xié)議,再加上SMBus-ARP 協(xié)議則可以輕松解決這個(gè)技術(shù)難題。

          TI 新推出的MSPM0L1306 系列MCU 不僅支持SMBus 協(xié)議,而且支持到了SMBus 3.0,領(lǐng)先同行的MCU??此朴侄嗔艘粋€(gè)協(xié)議層,但我們具體實(shí)現(xiàn)步驟依然非常簡單,僅需要根據(jù)共享充電寶的序列號來生成SMBus 協(xié)議下的UDID(128bit 數(shù)據(jù))即可。當(dāng)我們把共享充電寶插入充電槽后,MSPM0L1306 則主動(dòng)向Host 發(fā)起Notify 命令,當(dāng)充電站Host 接收到Notify 通知后,則按協(xié)議要求發(fā)起SMBus-ARP 流程,開始按步驟為共享充電寶分配當(dāng)前從地址。當(dāng)SMBus-ARP 流程完成后,充電寶則有自己的從地址(離開插槽失效),而充電站也記錄下當(dāng)前已經(jīng)有共享充電寶插入,并分配了從地址。充電站之后則按此分配的從地址進(jìn)行通訊。

          在本項(xiàng)目中,我們還實(shí)現(xiàn)SMBus 協(xié)議命令中的BlockRead/Write 命令,用于充電站(Host)向共享充電寶獲取和寫入數(shù)據(jù)。

          4.10 ADC,OPA,COMP模擬外設(shè)

          共享充電寶在充、放電過程中,我們需要對其進(jìn)行監(jiān)測,監(jiān)測充電寶當(dāng)前的運(yùn)行狀態(tài),保護(hù)其不超壓,不過放,在短路、超壓等情況發(fā)生下,快速切斷連接;也要測量電流,用于統(tǒng)計(jì)充、放電量的數(shù)值。上述功能的實(shí)現(xiàn),在MSPM0L1306 芯片下,其已經(jīng)全部集成于一身,不需要增加外圍器件。我們輕松使用12bit 的ADC 來測量電池電壓,使用COMP 比較器快速響應(yīng)過流,短路的情況發(fā)生;使用OPA 外設(shè),輕松實(shí)現(xiàn)PD 協(xié)議下充電電壓的范圍變化而不影響測量精度。

          5   系統(tǒng)實(shí)現(xiàn)

          5.1 引腳分配

          image.png

          5.2 軟件架構(gòu)

          本項(xiàng)目軟件架構(gòu)相對簡潔,主要分為兩大部分:

          一、充、放電狀態(tài)監(jiān)測;

          二、與充電站通訊;

          5.2.1 流程圖

          1737353067801622.png

          5.2.1 核心數(shù)據(jù)結(jié)構(gòu)

          當(dāng)共享充電寶返回充電站后,充電站需要收集共享充電寶的使用狀態(tài),如本次充電時(shí)長,本次充電電量,本次放電時(shí)長,本次放電電量,當(dāng)前電池電壓,當(dāng)前電量,累計(jì)充電時(shí)長,累計(jì)充電電量,累計(jì)放電時(shí)長,累計(jì)放電電量等。我設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)如下:

          typedef struct run_reg_s

          {

          uint32_t latest_charge_seconds;

          uint32_t latest_charge_quantity;

          uint32_t latest_discharge_seconds;

          uint32_t latest_discharge_quantity;

          uint32_t now_battery_voltage;

          uint32_t now_quantity;

          uint32_t total_charge_seconds;

          uint32_t total_charge_quantity;

          uint32_t total_discharge_seconds;

          uint32_t total_discharge_quantity;

          }run_reg_t;

          5.2.2 低功耗設(shè)計(jì)

          在本項(xiàng)目中,低功耗設(shè)計(jì)有兩種應(yīng)用場景:一、工作狀態(tài)下。當(dāng)系統(tǒng)空閑時(shí),進(jìn)入sleep 狀態(tài),以節(jié)省功耗;二、在共享充電寶低電量情況,則MSPM0L1306 進(jìn)入深度休眠。

          5.3 核心代碼

          5.3.1 按鍵代碼實(shí)現(xiàn)

          #include “keyscan.h”

          #include “ti/devices/msp/m0p/mspm0l130x.h”

          #include “ti/driverlib/dl_gpio.h”

          uint32_t keyscan_cnt;

          key_scan_t key_s2 = {.state = key_init, .code =

          0x00};

          void keyscan_poll(key_scan_t *key) {

          uint32_t ret = 0;

          switch (key->state) {

          case key_init: {

          break;

          }

          case key_wait: {

          ret = DL_GPIO_readPins(GPIOA, DL_GPIO_

          PIN_14);

          if (ret == 0) {

          key->state = key_confi rm;

          }

          break;

          }

          case key_confi rm: {

          ret = DL_GPIO_readPins(GPIOA, DL_GPIO_

          PIN_14);

          if (ret == 0) {

          key->state = key_up;

          } else {

          key->state = key_wait;

          }

          break;

          }

          case key_up: {

          ret = DL_GPIO_readPins(GPIOA, DL_GPIO_PIN_14);

          if (ret != 0) {

          key->state = key_up_confirm;

          }

          break;

          }

          case key_up_confirm: {

          ret = DL_GPIO_readPins(GPIOA, DL_GPIO_PIN_14);

          if (ret == 0) {

          key->state = key_up;

          } else {

          key->code = 0x01;

          key->state = key_trigger;

          }

          break;

          }

          case key_trigger: {

          break;

          }

          }

          }

          5.3.2 Uart串口輸出實(shí)現(xiàn)

          #include <stdio.h>

          #include <stdint.h>

          #include <string.h>

          #include <stdarg.h>

          #include <stdlib.h>

          #include <ti/devices/msp/msp.h>

          #include <ti/driverlib/driverlib.h>

          #include <ti/driverlib/m0p/dl_core.h>

          #include “ti_msp_dl_config.h”

          #include “l(fā)og.h”

          #if (LOG_PRINT_ENABLE == 1)

          uint8_t log_printf_buf[128] = {0};

          uint32_t log_buf_len = 0;

          void log_out(uint8_t *buf, uint32_t len)

          {

          uint32_t i;

          for (i = 0; i < len; i++)

          {

          DL_UART_transmitDataBlocking(UART_0_INST, buf[i]);

          }

          }

          void log_printf(const uint8_t *format, ...)

          {

          va_list ptr;

          va_start(ptr, format);

          log_buf_len = vsprintf(log_printf_buf, format,

          ptr);

          va_end(ptr);

          log_out(log_printf_buf, log_buf_len);

          }

          #endif

          5.3.3 LED呼吸燈

          static void rgb_ctrl(uint16_t rv, uint16_t gv, uint16_t bv) {

          DL_Timer_setCaptureCompareValue(PWM_1_INST, rv, GPIO_PWM_1_C0_IDX);

          DL_Timer_setCaptureCompareValue(PWM_0_INST, gv, GPIO_PWM_0_C1_IDX);

          DL_Timer_setCaptureCompareValue(PWM_1_INST, bv, GPIO_PWM_1_C1_IDX);

          }

          static void led_rgb_show(void) {

          static uint8_t led_seq = 0;

          static uint16_t pwm_value = 0;

          switch (led_seq) {

          case 0: {

          rgb_ctrl(pwm_value, 0, 0);

          if (pwm_value < 1000) {

          pwm_value += 100;

          } else {

          pwm_value = 0;

          led_seq = 1;

          }

          break;

          }

          case 1: {

          rgb_ctrl(0, pwm_value, 0);

          if (pwm_value < 1000) {

          pwm_value += 100;

          } else {

          pwm_value = 0;

          led_seq = 2;

          }

          break;

          }

          case 2: {

          rgb_ctrl(0, 0, pwm_value);

          if (pwm_value < 1000) {

          pwm_value += 100;

          } else {

          pwm_value = 0;

          led_seq = 0;

          }

          break;

          }

          }

          5.3.4 ADC采樣

          rt_adc_state = adc_idle;

          NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);

          /* Confirm VREF has settled before triggeringADC12 conversion */

          while (DL_VREF_CTL1_READY_NOTRDY ==DL_VREF_getStatus(VREF))

          ;

          while (1)

          {

          if (timeline_ms > 1000)

          {

          timeline_ms = 0;

          DL_GPIO_togglePins(GPIO_GRP_0_PORT,GPIO_GRP_0_PIN_0_PIN);

          if (rt_adc_state == adc_idle)

          {

          DL_ADC12_startConversion(ADC12_0_INST);

          rt_adc_state = adc_converting;

          }

          }

          if (rt_adc_state == adc_ready)

          {

          val = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_0);

          DL_ADC12_enableConversions(ADC12_0_INST);

          rt_temperature = thermistor_calc_temperature(val);

          6   項(xiàng)目展示

          6.1 擴(kuò)展板

          1737353114368498.png

          6.2 成品實(shí)物圖

          image.png

          7   經(jīng)驗(yàn)分享

          在開發(fā)過程中,我也遇到了一些困難,踩過一些坑。在這里也一并分享出來,希望對大家有所幫助。

          7.1 板載調(diào)試器XDS110

          TI 公司的XDS110 的名氣非常大,但在MSPM0L1306 開發(fā)板上使用起來非常簡單。我們只需要連接到電腦,看到任務(wù)管理器中已經(jīng)枚舉出來“XDS110”,打開Keil 軟件后,在debug 標(biāo)簽頁選擇”CMSIS-DAP”選項(xiàng)即可連接調(diào)試。

          所以,此XDS110 調(diào)試器,非彼XDS110。大家不要弄錯(cuò)喲!

          補(bǔ)充說明:在MSPM0L1306 的官方QuickGuide 文檔里面有特別提醒,只是我沒有仔細(xì)看。

          8   項(xiàng)目總結(jié)

          我們突出分享I2C-SMBus,低功耗與模塊外設(shè)這三個(gè)特性,主要是TI MSPM0L1306 芯片內(nèi)部完美集成。我在電路設(shè)計(jì)時(shí),無需再使用外圍器件實(shí)現(xiàn),節(jié)約了PCB 面積,減少了BOM 物料,直接CostDown 了項(xiàng)目成本,而且還帶來了軟件實(shí)現(xiàn)的靈活性?!昂螛范粸槟??”

          9   致謝

          感謝TI 公司提供MSPM0L1306 開發(fā)板,讓我提早試用,完成原型開發(fā),這必將會節(jié)省我實(shí)際項(xiàng)目的開發(fā)時(shí)間,也會讓我更加從容面對項(xiàng)目周期的壓力。

          感謝EEPW 論壇提供各種幫助,讓我有機(jī)會分享我的小作品。

          感謝其他在本原型開發(fā)過程中幫助我的人。再次感謝您的收聽,收看。

          (本文來源于《EEPW》



          關(guān)鍵詞: 202501

          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();