日韩一区二区三区精品,欧美疯狂xxxxbbbb牲交,热99re久久免费视精品频,人妻互换 综合,欧美激情肉欲高潮视频

歷史上的今天

今天是:2025年07月27日(星期日)

2019年07月27日 | STM32虛擬串口usb_printf函數(shù)及接收函數(shù)

發(fā)布者:tmgouzi 來(lái)源: eefocus關(guān)鍵字:STM32  虛擬串口  usb_printf函數(shù)  接收函數(shù) 手機(jī)看文章 掃描二維碼
隨時(shí)隨地手機(jī)看文章

環(huán)境:STM32CubeMX   STM32F429IGT6  STlink


首先要確保硬件電路USB部分沒問題;USB相關(guān)的概念知識(shí)大概需要了解一下,網(wǎng)上挺多這類文章的,自行百度。

點(diǎn)擊USB_OTG_FS,模式選擇Device_Only,其他保持默認(rèn)。


點(diǎn)擊USB_DEVICE,選擇IP 為VPC(虛擬串口),其他保持默認(rèn)。


我使用的芯片是F429IGT6,最大時(shí)鐘180MHz,但是USB時(shí)鐘必須為48MHz(詳情看STM32中文參考手冊(cè)930頁(yè)),180MHz是分頻不出來(lái)48MHz的USB時(shí)鐘,所以把系統(tǒng)配置成168MHz就能分頻出48MHz的USB時(shí)鐘。

堆空間需要改大一點(diǎn),不然在USB插入電腦的時(shí)候,設(shè)備管理器會(huì)顯示虛擬串口設(shè)備黃色感嘆號(hào)。因?yàn)樵赨SB插入電腦,STM32會(huì)創(chuàng)建一個(gè)實(shí)例,malloc申請(qǐng)內(nèi)存,但內(nèi)存不足的時(shí)候就失敗了,驅(qū)動(dòng)工作不正常了。


源碼在usbd_cdc.c中: 


pdev->pClassData = USBD_malloc(sizeof (USBD_CDC_HandleTypeDef));

最后生成代碼即可,打開工程。



圖中Application/User文件夾中多了幾個(gè)文件:


usb_device.czhi只有一個(gè)USB設(shè)備函數(shù)初始化函數(shù) MX_USB_DEVICE_Init()。


usb_conf.c是USB協(xié)議參數(shù)、IO初始化、中斷回調(diào)函數(shù)、端點(diǎn)打開關(guān)閉停止操作等等函數(shù)。


usbd_cdc_if.c有虛擬串口的接收和發(fā)送等函數(shù)。


usb_desc.c有USB的描述符和USB枚舉處理等。


文件夾Middlewares/USB_Device_Library是STM32Cube庫(kù)。


檢測(cè)VCP連接狀態(tài)

在中斷函數(shù)OTG_FS_IRQHandler


                         HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS);


                                       HAL_PCD_ConnectCallback(hpcd);    //連接事件回調(diào)


                                       HAL_PCD_DisconnectCallback(hpcd);    //斷開事件回調(diào)


發(fā)現(xiàn)兩個(gè)連接狀態(tài)事件回調(diào)函數(shù),但是經(jīng)過測(cè)試發(fā)現(xiàn)這兩個(gè)回調(diào)函數(shù)根本不會(huì)發(fā)生。具體往下就沒去深究了。


USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef  *pdev)

{

  /* Free Class Resources */

  pdev->dev_state = USBD_STATE_DEFAULT;

  pdev->pClass->DeInit(pdev, pdev->dev_config);  

  return USBD_OK;

}

 

 

 

void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)

{

    USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData);

}

但是偶然發(fā)現(xiàn)斷開事件有改變一個(gè)變量pdev->dev_state = USBD_STATE_DEFAULT;


所以發(fā)現(xiàn)hUsbDeviceFS.dev_state的狀態(tài)才是真正的連接狀態(tài)標(biāo)志位。


/*  Device Status */

#define USBD_STATE_DEFAULT                                1              //初始化狀態(tài)

#define USBD_STATE_ADDRESSED                              2              //建立地址

#define USBD_STATE_CONFIGURED                             3              //配置完成,連接成功

#define USBD_STATE_SUSPENDED                              4              //usb掛起,斷開成功

檢測(cè)USB狀態(tài)的函數(shù)


void VCP_Status(void)

{

    static uint8_t old_status = 0;

 

    if(hUsbDeviceFS.dev_state != old_status)

    {

        if(hUsbDeviceFS.dev_state == USBD_STATE_CONFIGURED)

            printf("連接成功rn");

        else if (hUsbDeviceFS.dev_state == USBD_STATE_SUSPENDED)

            printf("斷開成功rn");

        old_status = hUsbDeviceFS.dev_state;

    }    

}

 


打印函數(shù)

 


寫一個(gè)usb_printf打印函數(shù),在usbd_cdc_if.c里面末尾USER CODE BEGIN及USER CODE END之間添加


/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */

 

#include

 

void usb_printf(const char *format, ...)

{

    va_list args;

    uint32_t length;

 

    va_start(args, format);

    length = vsnprintf((char *)UserTxBufferFS, APP_TX_DATA_SIZE, (char *)format, args);

    va_end(args);

    CDC_Transmit_FS(UserTxBufferFS, length);

}

 

/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */

 


 


關(guān)于接收有幾點(diǎn)注意事項(xiàng),認(rèn)真看看。

1、usb虛擬串口每次接收最大的數(shù)據(jù)包ReceivePacket是64個(gè)字節(jié);且每包數(shù)據(jù)以末尾追加  rn 表示一包數(shù)據(jù)接收完整。


 

當(dāng)包長(zhǎng)小于64個(gè)字節(jié)的時(shí)候

修改USB接收打印函數(shù),在usbd_cdc_if.c里先找到static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)這個(gè)函數(shù),


把它改成下圖類似:


PC的usb虛擬串口收到MCU的數(shù)據(jù)通過UARTx發(fā)送回PC。演示一下發(fā)現(xiàn)什么問題:


//Len是每包數(shù)據(jù)的有效數(shù)據(jù)長(zhǎng)度。值不會(huì)超過64

static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)

{

    USBD_CDC_ReceivePacket(&hUsbDeviceFS);

    printf("%srn", Buf);

    memset(Buf, 0, APP_RX_DATA_SIZE);

    return (USBD_OK);

}


可以看到第一次發(fā)送內(nèi)容  01                  >>>     MUC收到的數(shù)據(jù)是:01 81 7F 04 0D 0A 。數(shù)據(jù)異常,多了中間的 81 7F 04。


可以看到第二次發(fā)送內(nèi)容  01 02 03 04   >>>     MUC收到的數(shù)據(jù)是:01 02 03 04 0D 0A 。數(shù)據(jù)正常。



注意static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)的  *Len 是每包數(shù)據(jù)真實(shí)有效長(zhǎng)度;



第一次發(fā)送的內(nèi)容,*Len是等于1的;


第二次發(fā)送的內(nèi)容,*Len是等于4的;


*Len最大不會(huì)超過64。


出現(xiàn)第一種情況的原因是:當(dāng)包長(zhǎng)小于64個(gè)字節(jié)的時(shí)候,數(shù)據(jù)會(huì)強(qiáng)制32bit對(duì)齊。也就是發(fā)的字節(jié)必須要是4的倍數(shù),不夠補(bǔ)夠4的倍數(shù),最后末尾加上rn表示包的完整。


為什么會(huì)32位對(duì)齊,下面是STM32的源碼:


typedef struct

{

  uint32_t data[CDC_DATA_HS_MAX_PACKET_SIZE/4];      /* Force 32bits alignment */

  ...

  ...

}

USBD_CDC_HandleTypeDef;


當(dāng)包長(zhǎng)大于64個(gè)字節(jié)的時(shí)候

發(fā)現(xiàn)一共發(fā)送了306個(gè)字節(jié)。但是MCU收到了318個(gè)字節(jié)。318怎么來(lái)的?


其實(shí)每64個(gè)字節(jié)加rn2個(gè)字節(jié),最后一包數(shù)據(jù)不夠4倍數(shù)再補(bǔ)充夠4的倍數(shù)。


306 / 64 = 4......50


4 * 13 >= 50


也就是4 * (64 + rn) + 52個(gè)字節(jié) + rn = 318。


故修改代碼:以接收到rn為結(jié)束


typedef struct{

  uint32_t rxlen;

  uint32_t flag;

}VcpRx_t;

 

VcpRx_t temp = {

    .rxlen =0,

    .flag = 0

};

 

static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)

{

  /* USER CODE BEGIN 6 */   

    temp.rxlen = temp.rxlen + (*Len);

    

    if(temp.rxlen < APP_RX_DATA_SIZE && UserRxBufferFS[temp.rxlen - 2] != 0x0d 

        &&  UserRxBufferFS[temp.rxlen - 1] != 0x0a)

    {

       //---繼續(xù)接收---------------

       USBD_CDC_SetRxBuffer(&hUsbDeviceFS,UserRxBufferFS  + temp.rxlen); 

       USBD_CDC_ReceivePacket(&hUsbDeviceFS);

    }

    else temp.flag = 1;    //接收完成

 

    return (USBD_OK);

  /* USER CODE END 6 */

}

 

 

 

 

//接收完成后通過UART打印出來(lái)

void rxdata_printf(void)

{

  if(temp.flag)

  {

    printf("%srn", UserRxBufferFS);

    temp.flag = 0;

    temp.rxlen = 0;

    memset(UserRxBufferFS, 0, APP_RX_DATA_SIZE);

    USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS); 

    USBD_CDC_ReceivePacket(&hUsbDeviceFS);

  }

}

main函數(shù)


int main(void)

{

    HAL_Init();

 

    SystemClock_Config();

 

    MX_GPIO_Init();

    MX_USB_DEVICE_Init();

    MX_USART2_UART_Init();

    MX_USART1_UART_Init();

    /* USER CODE BEGIN 2 */

    printf("sudarootrn");

 

    while (1)

    {

        rxdata_printf();       

    }

}

附上測(cè)試代碼:https://download.csdn.net/download/sudaroot/10975317


 


2019.07.24改進(jìn),源碼沒更新。

下面這個(gè)函數(shù)作用是避免我們每次下載復(fù)位后需要撥出USB再插上才能用。如果不行的話可以把HAL_Delay()延時(shí)加大一些。


原理:和usb硬件相關(guān)。PC的usb內(nèi)部?jī)筛鶖?shù)據(jù)線都接著下拉電阻,當(dāng)檢測(cè)任一個(gè)任一根數(shù)據(jù)線有高電平代表有設(shè)備接入初始化。下面代碼就是模擬,上電把兩個(gè)STM32的USB IO拉低,相當(dāng)于手動(dòng)斷開USB線,然后進(jìn)行MX_USB_DEVICE_Init()初始化的時(shí)候會(huì)正確初始化這兩個(gè)IO。


static void USB_Status_Init(void)

{

    GPIO_InitTypeDef GPIO_InitStruct = {0};

 

    /* GPIO Ports Clock Enable */

    __HAL_RCC_GPIOA_CLK_ENABLE();

 

    /*Configure GPIO pin Output Level */

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11 | GPIO_PIN_12, GPIO_PIN_RESET);

 

    /*Configure GPIO pin : W25Q256_CS_Pin */

    GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12;

    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

    GPIO_InitStruct.Pull = GPIO_PULLDOWN;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    HAL_Delay(2);

}

使用方法:


在main()函數(shù)中的 SystemClock_Config()函數(shù)調(diào)用后使用USB_Status_Init();



VCP通訊走的是pack,故和串口調(diào)試助手的波特率無(wú)關(guān)。無(wú)論波特率多少,對(duì)數(shù)據(jù)無(wú)影響。


全篇完。

關(guān)鍵字:STM32  虛擬串口  usb_printf函數(shù)  接收函數(shù) 引用地址:STM32虛擬串口usb_printf函數(shù)及接收函數(shù)

上一篇:STM32 F103USB官方例程枚舉知識(shí)
下一篇:STM32 USB 枚舉分析

推薦閱讀

該智能機(jī)器人集成了熱成像系統(tǒng)、核輻射監(jiān)測(cè)系統(tǒng)等檢疫執(zhí)法科技,在口岸巡查時(shí)可大范圍、有效篩查出入境旅客及其攜帶的行李。如發(fā)現(xiàn)旅客體溫異常(高于37.3 )、攜帶放射性超標(biāo)物品或凍肉、水果等禁止進(jìn)境物,機(jī)器人會(huì)即時(shí)發(fā)送嫌疑人員及物品的圖像信息到終端及關(guān)聯(lián)移動(dòng)終端,以便檢驗(yàn)檢疫工作人員快速布控。同時(shí),該機(jī)器人能根據(jù)工作人員指令,發(fā)出報(bào)警...
在商務(wù)部舉行的例行記者會(huì)上,新聞發(fā)言人高峰對(duì)美國(guó)CAPE公司禁止和大疆公司合作一事做出回應(yīng)稱,美國(guó)國(guó)內(nèi)一些人在沒有任何事實(shí)依據(jù)的情況下,捕風(fēng)捉影,憑空抹黑,借口安全風(fēng)險(xiǎn),打壓中國(guó)企業(yè),但最終損害的將是他們自身的利益。 高峰強(qiáng)調(diào):中國(guó)政府一貫要求中國(guó)的企業(yè)合法合規(guī)經(jīng)營(yíng),既要遵守國(guó)際規(guī)則,也要遵守所在國(guó)的法律法規(guī),我們支持中國(guó)企業(yè)在平等...
最近,阿里宣布,國(guó)內(nèi)最大的智能語(yǔ)音芯片商全志科技和平頭哥達(dá)成戰(zhàn)略合作,全志科技將基于平頭哥玄鐵處理器研發(fā)全新計(jì)算芯片,用于工業(yè)控制、智能家居及消費(fèi)電子領(lǐng)域,并預(yù)計(jì)3年內(nèi)出貨將達(dá)到5000萬(wàn)顆。 成立短短兩年,平頭哥發(fā)布了多款重磅新產(chǎn)品,最不易的是其IP產(chǎn)品如今迎來(lái)了大客戶,這難道是要成為下一個(gè)"ARM"的節(jié)奏么? 平頭哥是阿里巴巴于2018年9月成...
VCSEL激光LiDAR成自動(dòng)駕駛汽車必備,測(cè)試給未來(lái)更強(qiáng)保障隨著激光雷達(dá)成為自動(dòng)駕駛汽車的必備,越來(lái)越多的企業(yè)加入對(duì)激光雷達(dá)的新應(yīng)用開發(fā)和對(duì)先進(jìn)技術(shù)的追求,核心傳感器成為科技企業(yè)的戰(zhàn)略重地,特別是組成固態(tài)車載雷達(dá)的主體VCSEL激光LiDAR成為必爭(zhēng)之地。新的VCSEL激光LiDAR需求中,即有遠(yuǎn)程測(cè)距的高功率雷達(dá),也有替代紅外與超聲波等環(huán)境感知傳感器的普...

史海拾趣

問答坊 | AI 解惑

急求一個(gè)匯編程序!

急求一個(gè)匯編程序,能在8051或是8031芯片的LCD顯示器上顯示幾個(gè)漢字:例如:中國(guó)人民銀行,而且能實(shí)現(xiàn)上下滾動(dòng)的效果!關(guān)系的能不能畢業(yè)了,哪位大哥是這方面的高手,請(qǐng)幫幫我啊!   我QQ是153904006 …

查看全部問答∨

EVC4.0下出現(xiàn)cannot open file 'mfcs42d.lib'如何處理???

我新建了一個(gè)基于對(duì)話框的MFC,但是為什么一編譯現(xiàn)如下的錯(cuò)誤: LINK : fatal error LNK1104: cannot open file \'mfcs42d.lib\' 不知道我應(yīng)該如何做才能解決這個(gè)問題呢??…

查看全部問答∨

D題中的用3.6V電源供電,電源自制是什么意思?

本帖最后由 paulhyde 于 2014-9-15 08:55 編輯 是自制220V變到3.6V的電源么?謝謝。。  …

查看全部問答∨

使用ad7730的模式寄存器問題

請(qǐng)教各位大俠,使用ad7730的模式寄存器為什么讀出與寫入不一樣呢?而且寄存器讀出的全是FFFFFF。…

查看全部問答∨

易電源的使用心得(電源總動(dòng)員活動(dòng))

今年六月份有幸獲得了易電源的使用機(jī)會(huì),也對(duì)易電源做了幾項(xiàng)簡(jiǎn)單的測(cè)試,主要是對(duì)易電源的散熱性和紋波和效率做了一些測(cè)試,由于之前活動(dòng)已經(jīng)總結(jié)了,也就不詳細(xì)介紹了,總的來(lái)說(shuō)感覺易電源的散熱性還是蠻不錯(cuò)的,我當(dāng)時(shí)在5V供電了三十分鐘多用熱偶 ...…

查看全部問答∨

關(guān)于SEED-EXP430F5529 旋轉(zhuǎn)立方體的程序買了板子的同學(xué)戳進(jìn)來(lái)

最近 SEED-EXP430F5529   好火的樣子, 看到壇友秀板子的時(shí)候提到了一個(gè) 顯示一個(gè)旋轉(zhuǎn)的立方體的例子,我也想在12864 上 實(shí)現(xiàn),求有程序的童鞋 發(fā)我 一份啊, 謝謝了?!?

查看全部問答∨

傳三星正研發(fā)智能隱形眼鏡 已用兔子開始試驗(yàn)

一組研究機(jī)構(gòu)已經(jīng)開發(fā)出了一種新的納米材料,可以用來(lái)制作智能隱形眼鏡(就像是戴在眼球上的谷歌(微博)眼鏡)。這組研究機(jī)構(gòu)中有三星的兩個(gè)部門。該項(xiàng)目的負(fù)責(zé)人Jang-Ung Park表示:“我們的目標(biāo)是制作可穿戴的隱形眼鏡,它可以做到谷歌眼鏡能做 ...…

查看全部問答∨

2013電賽E題復(fù)測(cè)隊(duì)伍

本帖最后由 paulhyde 于 2014-9-15 03:06 編輯 2013電賽E題復(fù)測(cè)隊(duì)伍 [ 本帖最后由 ylsj123456 于 2013-9-22 23:30 編輯 ]    …

查看全部問答∨
小廣播
設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦

最新單片機(jī)文章
更多每日新聞

 
EEWorld訂閱號(hào)

 
EEWorld服務(wù)號(hào)

 
汽車開發(fā)圈

 
機(jī)器人開發(fā)圈

電子工程世界版權(quán)所有 京ICP證060456號(hào) 京ICP備10001474號(hào)-1 電信業(yè)務(wù)審批[2006]字第258號(hào)函 京公網(wǎng)安備 11010802033920號(hào) Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved