環(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ú)影響。 全篇完。
上一篇:STM32 F103USB官方例程枚舉知識(shí)
下一篇:STM32 USB 枚舉分析
推薦閱讀
史海拾趣
隨著公司的發(fā)展,Avalon Photonics開始尋求國(guó)際合作,以進(jìn)一步拓展市場(chǎng)。公司與歐洲一家知名的科研機(jī)構(gòu)建立了戰(zhàn)略合作關(guān)系,共同研發(fā)新一代的光子學(xué)設(shè)備。這一合作不僅帶來(lái)了技術(shù)上的互補(bǔ),也為Avalon打開了歐洲市場(chǎng)的大門。通過國(guó)際合作,Avalon的產(chǎn)品逐漸在國(guó)際市場(chǎng)上獲得認(rèn)可,公司規(guī)模也逐步擴(kuò)大。
在面臨激烈的市場(chǎng)競(jìng)爭(zhēng)時(shí),Bellin Dynamic Systems選擇與行業(yè)內(nèi)的其他領(lǐng)軍企業(yè)展開戰(zhàn)略合作。通過與這些企業(yè)的合作,Bellin Dynamic Systems不僅獲得了更多的技術(shù)資源和市場(chǎng)渠道,還共同推動(dòng)了整個(gè)行業(yè)的發(fā)展。這種合作共贏的模式使得Bellin Dynamic Systems在競(jìng)爭(zhēng)中保持了領(lǐng)先地位。
技術(shù)創(chuàng)新是Clover Display Limited得以持續(xù)發(fā)展的核心動(dòng)力。公司高度重視研發(fā)團(tuán)隊(duì)的建設(shè),不僅在香港設(shè)立了一支強(qiáng)大的研發(fā)團(tuán)隊(duì),還不斷引進(jìn)國(guó)內(nèi)外優(yōu)秀人才。這些研發(fā)人員致力于開發(fā)液晶顯示器(LCD)及液晶顯示屏(LCM)的新應(yīng)用,為公司帶來(lái)了眾多具有市場(chǎng)競(jìng)爭(zhēng)力的產(chǎn)品。在他們的努力下,Clover Display Limited在液晶顯示技術(shù)領(lǐng)域取得了多項(xiàng)突破,為公司的快速發(fā)展奠定了堅(jiān)實(shí)基礎(chǔ)。
在市場(chǎng)競(jìng)爭(zhēng)日益激烈的情況下,Clever Little Box意識(shí)到,單打獨(dú)斗很難取得長(zhǎng)久的成功。于是,公司開始積極尋求與其他企業(yè)的合作,通過共贏的戰(zhàn)略選擇,實(shí)現(xiàn)資源共享、優(yōu)勢(shì)互補(bǔ)。這種合作模式不僅幫助公司擴(kuò)大了市場(chǎng)份額,還提高了公司的品牌知名度和影響力。
隨著公司實(shí)力的不斷增強(qiáng),Clever Little Box開始將目光投向國(guó)際市場(chǎng)。公司制定了國(guó)際化戰(zhàn)略,通過參加國(guó)際展覽、建立海外銷售渠道等方式,積極開拓海外市場(chǎng)。這一戰(zhàn)略的實(shí)施不僅為公司帶來(lái)了更廣闊的市場(chǎng)空間,還提高了公司的國(guó)際競(jìng)爭(zhēng)力。
需要注意的是,以上故事是基于公開信息和一般企業(yè)發(fā)展規(guī)律進(jìn)行的概括和推測(cè),并非Clever Little Box公司的真實(shí)發(fā)展歷程。如需了解該公司更準(zhǔn)確、具體的發(fā)展故事,建議查閱相關(guān)資料或訪問公司官方網(wǎng)站。
在市場(chǎng)競(jìng)爭(zhēng)日益激烈的情況下,Clever Little Box意識(shí)到,單打獨(dú)斗很難取得長(zhǎng)久的成功。于是,公司開始積極尋求與其他企業(yè)的合作,通過共贏的戰(zhàn)略選擇,實(shí)現(xiàn)資源共享、優(yōu)勢(shì)互補(bǔ)。這種合作模式不僅幫助公司擴(kuò)大了市場(chǎng)份額,還提高了公司的品牌知名度和影響力。
急求一個(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è)問題呢??… 查看全部問答∨ |
|
今年六月份有幸獲得了易電源的使用機(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)是制作可穿戴的隱形眼鏡,它可以做到谷歌眼鏡能做 ...… 查看全部問答∨ |
本帖最后由 paulhyde 于 2014-9-15 03:06 編輯 2013電賽E題復(fù)測(cè)隊(duì)伍 [ 本帖最后由 ylsj123456 于 2013-9-22 23:30 編輯 ] … 查看全部問答∨ |
設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦
- 神經(jīng)形態(tài)芯片可能是革新機(jī)器人實(shí)時(shí)電機(jī)控制的未來(lái)
- 從三個(gè)方面理解ARM嵌入式系統(tǒng)
- 自動(dòng)報(bào)警 基于MCU的家庭防盜報(bào)警系統(tǒng)的設(shè)計(jì)
- 存儲(chǔ)控制器及其訪問外設(shè)的原理
- 基于51系列單片機(jī)的智能照明控制系統(tǒng)設(shè)計(jì)方案
- 基于STM32的四旋翼飛行器控制系統(tǒng)
- 單片機(jī)應(yīng)用編程技巧解析
- 基于89C52的教室智能節(jié)能照明系統(tǒng)設(shè)計(jì)
- 一種新型的雨量光照傳感器的設(shè)計(jì)
- 答題抽獎(jiǎng):Mentor Tessent Automotive相關(guān)測(cè)試解決方案(獎(jiǎng)品池還剩不少獎(jiǎng)品喲)
- 您的無(wú)人機(jī)安全嗎?使用電路保護(hù)應(yīng)對(duì)安全隱患
- EE團(tuán)--TI 原裝DK-LM3S9B96開發(fā)板 348元(包郵)!
- 手印簽到,共同見證 TI 中國(guó)大學(xué)計(jì)劃20周年
- ADI有獎(jiǎng)下載活動(dòng)之15 ADI公司智能可穿戴醫(yī)療保健設(shè)備解決方案
- 希望一月 愛上EEWORLD——論壇推廣月
- 免費(fèi)下載Vishay最新汽車解決方案
- 伯克利科學(xué)家研發(fā)出,可以預(yù)見未來(lái)事情的機(jī)器人,將用于交通預(yù)測(cè)路況
- 微型折疊式飛行機(jī)器人已問世,可用于探索大面積未知空間任務(wù)
- 未來(lái)沒來(lái),但中國(guó)已成為機(jī)器人的試驗(yàn)場(chǎng)
- 中國(guó)品牌Diqee掃地機(jī)器人,存在兩個(gè)安全漏洞,導(dǎo)致容易被黑客攻擊
- 智能裝備市場(chǎng)規(guī)模及發(fā)展預(yù)測(cè)分析
- Facebook正發(fā)自己的操作系統(tǒng)要擺脫對(duì)安卓的依
- 蘋果組建“秘密團(tuán)隊(duì)” 研發(fā)衛(wèi)星直接數(shù)據(jù)傳輸?shù)搅嗽O(shè)備
- Galaxy Fold 2曝光:上下豎向折疊+打孔屏設(shè)計(jì)?
- 摩托羅拉延遲折疊機(jī)Razr上市
- iOS 13.3正式版發(fā)布一周:蘋果關(guān)閉了iOS 13.2.3驗(yàn)證