GD32 使用stm32 固件库
1、 系統(tǒng)
????1) 晶振起振區(qū)別
????描述:啟動(dòng)時(shí)間,GD32 與STM32 啟動(dòng)時(shí)間都是2ms,實(shí)際上GD 的執(zhí)行效率快,所以ST 的HSE_STARTUP_TIMEOUT ((uint16_t)0x0500)是2ms,但是這個(gè)宏定義值在GD 上時(shí)間就更加短了,所以要加大這個(gè)值的設(shè)置。
????解決方法:將宏定義:
#define HSE_STARTUP_TIMEOUT ((uint16_t)0x0500)
修改為:
#define HSE_STARTUP_TIMEOUT ((uint16_t)0xFFFF)
備注:啟動(dòng)時(shí)間宏定義所在位置:
????1、在V3.X 的庫(kù),其啟動(dòng)時(shí)間宏定義在stm32f10x.h 頭文件中(路徑:\..\Libraries\CMSIS\CM3)。(庫(kù)版本的不同,所在目錄也有所不同)
????2、在V3.0 以前的庫(kù),其啟動(dòng)時(shí)間宏定義在stm32f10x_rcc.c 源文件中(HSEStartUp_TimeOut)(路徑:\..\Libraries\STM32F10x_StdPeriph_Driver\src)。
????2) 部分客戶使用有源晶振出現(xiàn)問(wèn)題,在GD32F103 小容量產(chǎn)品,發(fā)現(xiàn)會(huì)在MCU 的復(fù)位管腳一直把電平拉到0.89V,電平不能保持在高電平。
????描述:是由于部分有源晶振起振時(shí)間太快,復(fù)位信號(hào)還沒(méi)有完成導(dǎo)致的
????解決方法:就是在有源晶振的輸入端與地之前并上一個(gè)30pf電容。
????3) GD32 MCU 主頻支持108MHz 高性能,在代碼移植方面需要注意事項(xiàng)
????描述:GD32 通過(guò)芯片內(nèi)部加大緩存,提高了相同工作頻率下的代碼執(zhí)行速度,帶來(lái)了高性能的使用體驗(yàn)。
????解決方法:因此如果代碼有用到for 循環(huán)或while 循環(huán)語(yǔ)句做精確定時(shí)的,定時(shí)時(shí)間會(huì)由于代碼執(zhí)行速度加快而使循環(huán)的時(shí)間變短。使用Timer 定時(shí)器則沒(méi)有影響。
????4) GD32F105/107 系列MCU 配置為108MHz 有何不同
????描述:通過(guò)Clock configuration register (RCC_CFGR) 中, 第21 : 18 位為PLLMUL[3:0],再結(jié)合第29 位PLLMUL[4]組成5 位的位域來(lái)確定PLL 倍頻系數(shù),即通過(guò)軟件配置來(lái)定義PLL 的倍頻系數(shù),且PLL 輸出頻率絕對(duì)不得超過(guò)最高主頻(108MHz)。
2. 內(nèi)部Flash
????1) 芯片設(shè)置讀保護(hù)用法
????描述:由于GD 的Flash 是自己的專利技術(shù),STM 的Flash 是第三方提供的,所以GD 的Flash 和STM 的Flash 有些許差異。GD 的擦除時(shí)間會(huì)長(zhǎng)一點(diǎn).
????解決方法:在寫完KEY 序列以后,需要讀該位,確認(rèn)key 已生效。 所以,這里應(yīng)該插入
While( ! (FLASH->CR & 0x200 ) ); // Wait OPTWRE 或可簡(jiǎn)單插入兩個(gè)NOP。
__NOP();
__NOP();
在ST 庫(kù)中,只有
FLASH_Status FLASH_EraseOptionBytes(void)
FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data)
FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages)
FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState)
四個(gè)函數(shù)需要修改。
????2) IAP 在應(yīng)用中編程
????描述:GD32 由于自有flash 的0 訪問(wèn)時(shí)序,同STM32 在Flash 的Erase 和Program 上存在差別,GD32 的Erase 和Program 時(shí)間比STM32 的稍微長(zhǎng)些,建議對(duì)Erase 和Program 時(shí)間進(jìn)行修改。
????解決方法:將宏定義
#define EraseTimeout ((uint32_t)0x000B0000)
#define ProgramTimeout ((uint32_t)0x00002000)
修改為:
#define EraseTimeout ((uint32_t)0x000FFFFF)
#define ProgramTimeout ((uint32_t)0x0000FFFF)
備注: Erase 和Program 時(shí)間宏定義在stm32f10x_flash.c 源文件中
(路徑:\..\Libraries\STM32F10x_StdPeriph_Driver\src)
3) 用IAR 下載配置
????解決方法:在批量生產(chǎn)的時(shí)候首先會(huì)燒寫一個(gè)USB 的boot,這個(gè)boot 自動(dòng)運(yùn)行后在由上位機(jī)軟件進(jìn)行燒寫應(yīng)用程序。如果boot 程序不能自動(dòng)運(yùn)行則需要重新插拔一次電源。給生產(chǎn)造成一些麻煩。產(chǎn)生不能自動(dòng)運(yùn)行程序的原因是如果程序設(shè)置讀保護(hù)的話需要等待FLASH_CR 的第9[OPTWRE]位為1.如果沒(méi)有置位的話繼續(xù)執(zhí)行就會(huì)出錯(cuò)。由于ST 的執(zhí)行速度慢,程序執(zhí)行到讀FLASH_CR 寄存器的時(shí)候該位已經(jīng)置1,GD 的執(zhí)行速度比較快,程序運(yùn)行到這的時(shí)候該位還沒(méi)置1,因此需要在FLASH_ReadOutProtection 函數(shù)里面添加一些輪詢?cè)撐粸? 或者加一些延時(shí)。
3. ISP 燒寫軟件
????1) ISP 燒寫,建議使用官方燒寫軟件
????描述:GD32 芯片內(nèi)部flash 同STM32 有區(qū)別。
????解決方法:建議到www.mcuisp.com?下載最新版本的MCUISP。另外GD32 也有專門的燒寫軟件(GigaDevice MCU ISP Programmer)可以到http://bbs.21ic.com/gd32?論壇下載。如果使用自制的ISP 軟件或脫機(jī)編程器,實(shí)現(xiàn)ST 和GD 完全兼容,建議修改以下參數(shù):
????1、 頁(yè)擦除等待超時(shí)時(shí)間增加至300ms,整片擦除等待超時(shí)時(shí)間增加至3s 左右。
????2、 字編程等待超時(shí)時(shí)間增加至2ms,頁(yè)編程等等超時(shí)時(shí)間增加至300ms。
4.I/O 口
????1) IO 口外部中斷使用方法
????描述:在關(guān)閉期間,如果外部引腳有電平的變化,在使用IMR 打開中斷后會(huì)馬上進(jìn)入中斷服務(wù)程序。理論是打開中斷前,不管管腳是否有電平的變化,都不會(huì)影響到打開后的中斷響應(yīng)。
????解決方法:所以解決方法就是通過(guò)禁用上升沿或者下降沿檢測(cè)寄存器來(lái)開關(guān)中斷,不能使用IMR 屏蔽寄存器。程序如下:
EXTI->FTSR &= ~EXTI_Line3; //關(guān)閉沿檢測(cè),以達(dá)到關(guān)閉中斷的目的,下降沿使用FTSR 寄存器,上升沿使用RTSR 寄存器
EXTI->PR = EXTI_Line3;
EXTI->FTSR |= EXTI_Line3;
????2) 在待機(jī)模式,PA8 引腳特殊設(shè)置
????描述:在使用低功耗的情況下,PA8 會(huì)被MCU 在內(nèi)部被設(shè)置為地PA8 復(fù)用為MCU 內(nèi)部頻率輸出,超低功耗設(shè)置時(shí)需要懸空。
????解決方法:在待機(jī)模式,PA8 懸空不用。
????3) 低功耗下必須注意
????描述:在使用低功耗情況下,把軟件全部端口(A-F)時(shí)鐘關(guān)掉,無(wú)論是否有該端口。
4) 當(dāng)有脈沖群沖擊管腳
????描述:需要在在進(jìn)入中斷后關(guān)閉中斷。
5. 定時(shí)器
????1) 定時(shí)器輸入捕獲模式需要軟件清中斷
????描述:STM 定時(shí)器輸入捕獲模式默認(rèn)能硬件清中斷,GD 為了更加嚴(yán)格要求配置,需要做軟件清中斷 。
????解決方法:軟件清除標(biāo)志位。
????2) 定時(shí)器向上脈沖計(jì)數(shù)模式設(shè)置
????描述:定時(shí)器的用法差異。
????解決方法:脈沖計(jì)數(shù)模式下,裝載值必須設(shè)置為比預(yù)期值大,否則不計(jì)數(shù)在ST 上如果重載值不設(shè)置(初始為0)的時(shí)候,CNT 可以正常計(jì)數(shù)。 在GD 上如果重載值不設(shè)置保持初始為0 的時(shí)候,會(huì)因?yàn)橹剌d值為零,即便是來(lái)一個(gè)脈沖也會(huì)導(dǎo)致所有的寄存器復(fù)位從而不能正常計(jì)數(shù)。
????3) TIM、ADC 模塊
????描述:Timer、ADC 模塊的觸發(fā)信號(hào)寬度要求。
????解決方法:由于內(nèi)部有高速和低速兩條外圍總線,Timer、ADC 模塊和其他外設(shè)共同使用這兩個(gè)總線。GD32F103/101 系列Flash 128KB 及以下的型號(hào),Timer、ADC 等模塊識(shí)別觸發(fā)信號(hào)的條件是觸發(fā)信號(hào)寬度大于模塊所在總線的時(shí)鐘寬度。
6. 串口USART
????1) USART 連續(xù)發(fā)送數(shù)據(jù)字節(jié)有空閑位
????描述:字節(jié)間有空閑位。
????解決方法:對(duì)于一般的通訊來(lái)說(shuō),不會(huì)有影響,只對(duì)于一般在通訊上有特殊協(xié)議的,才會(huì)產(chǎn)生數(shù)據(jù)不準(zhǔn)確的情況所以,特定情況,修改程序。
7. I2C 總線
????1) 硬件I2C 特殊配置
????描述:GD 的I2C 相對(duì)STM 的來(lái)說(shuō)要少一個(gè)標(biāo)志位
????解決方法
????1、宏地址定義改變
#define I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED
((uint32_t)0x00060002)
#define I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED
((uint32_t)0x00070002)
????2、硬件I2C 在會(huì)在向從機(jī)發(fā)送7bits 地址完成后,從機(jī)還沒(méi)來(lái)得及識(shí)別。(看客戶應(yīng)用)我們可以在發(fā)送完7bits 后加個(gè)延時(shí),讓從機(jī)完全識(shí)別:
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);
{
int i = 0xfff;
while(i --);
}
????3、檢測(cè)ADDR 不能使用I2C_CheckEvent 函數(shù),因?yàn)樗麜?huì)清除ADDR,可以使用I2C_GetFlagStatus 函數(shù)。
就是把while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
改為while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR));
????4、還有個(gè)關(guān)于編程步驟的嚴(yán)謹(jǐn)性,跟STM 想比,我們是先Clear_ACK,再Clear_ARRD。
8. ADC 采集
????1) ADC 采樣設(shè)置
????描述:ADC 啟動(dòng)
????解決方法:
????1. 當(dāng)ADON=0 時(shí)寫入1 后,需要等待一段時(shí)間t_WAIT,如果用ST 庫(kù)的話就在ADC_CMD 后面加20us 左右的延時(shí)。
????2. 如果采用中斷獲得采樣數(shù)據(jù)后,需要軟件清除中斷。
9. SDIO
????1) SDIO DAT 3 pin 的在 1 bit bus mode 和4 bit bus mode 下的配置
????描述:
????1、 SDIO 在 1 bit bus mode 下,DAT 3 pin 是低電平,這樣會(huì)導(dǎo)致 SD Card 進(jìn)入SPI 模式。
????原因:初始化失敗的原因主要是因?yàn)镚D32 的芯片SDIO 的DAT3 口存在BUG。
????2、 在4 位模式下,通過(guò)上面的方法,程序能正常初始化,但不能正常讀寫SD卡。
????原因:因?yàn)镈AT3 口在前面已經(jīng)配置成推挽輸出,所以在4 位模式下,不能正常讀下。在調(diào)用4 位模式前,把DAT3 的端口配置成復(fù)用推挽輸入即可解決問(wèn)題。
????解決方法 1、 1 bit bus mode 的解決方法:建議在SDIO 使能之前,先把 SDIO DAT 3 pin 配置成推挽輸出,并且要置成高電平,使 SDIO DAT 3 pin 保持高電平即可.
????2、 4 bit bus mode 的解決方法:在調(diào)用4 位模式前,把DAT3 的端口配置成復(fù)用輸出即可解決問(wèn)題。
????2) 程序在剛燒完后能正常讀寫SD 卡,斷電再上電后,SD 卡初始化失敗,需要手動(dòng)復(fù)位一次后才正常
描述 在某些SD 卡中,GD32 斷電再上電,會(huì)引起SD 卡上的時(shí)鐘信號(hào)不正常,導(dǎo)致SD 卡發(fā)送命令失敗。
????解決方法:在程序中,打開SD 卡時(shí)鐘后,增加一小段延時(shí),以保證SD 卡時(shí)鐘信號(hào)穩(wěn)定。這個(gè)延時(shí)添加的地方:在sdcard.c(即SDIO 的配置文件中),然后在SD_Error SD_Init(void)這個(gè)函數(shù)中找到SDIO_DeInit();就在這個(gè)后面加個(gè)延時(shí)。
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
SDIO_DeInit();
{
int i = 0xffff;
while(i --);
}
10. USB
????A. USB_OTG
????1) 客戶使用STM32 的DFU 原工程時(shí)需要注意幾點(diǎn)
????解決方法:
????1、 在usb_istr.c 中,增加如下語(yǔ)句
for (i=0;i<8;i++) EP[i] = _GetENDPOINT(i);
for (i=0;i<8;i++)
_SetENDPOINT(i, EP[i] & 0x7070);
????2、 在usb_conf.h 中,按照下圖紅色字體語(yǔ)句進(jìn)行修改
#if defined(STM32L1XX_MD) || defined(STM32L1XX_HD)||
defined(STM32L1XX_MD_PLUS)
#define INTERN_FLASH_SECTOR_ERASE_TIME 100
#define INTERN_FLASH_SECTOR_WRITE_TIME 104
#else
#define INTERN_FLASH_SECTOR_ERASE_TIME 100
#define INTERN_FLASH_SECTOR_WRITE_TIME 100
????3、 把固件庫(kù)中的stm32f10x_flash.c 使用附件的進(jìn)行替換。
????4、 軟件進(jìn)行讀保護(hù)位時(shí)需要選使用FLASH_Unlock();函數(shù)
int main(void)
{
#if defined (USE_STM32L152D_EVAL)
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_OPTVERRUSR);
#endif
FLASH_Unlock();
FLASH_ReadOutProtection(ENABLE);
FLASH_Lock();
????2) 部分USB 兼容性
????解決方法:
????1. 部分U 盤有3 個(gè)端點(diǎn),數(shù)組越界導(dǎo)致Itf_Desc 被清空,所以主機(jī)不能識(shí)別設(shè)備類型。USBH_conf.h 文件的USBH_MAX_NUM_ENDPOINTS 的定義由2 改成3 就可以了將:#define USBH_MAX_NUM_ENDPOINTS 2
改為:#define USBH_MAX_NUM_ENDPOINTS 3
????2. 在In 端點(diǎn)中斷處理程序USB_OTG_USBH_handle_hc_n_In_ISR 中,對(duì)于NAK 中斷,V1.0.0 版本的處理如下:
else if (hcint.b.nak)
{
if(hcchar.b.eptype == EP_TYPE_INTR)
{
UNMASK_HOST_INT_CHH (num);
USB_OTG_HC_Halt(pdev, num);
CLEAR_HC_INT(hcreg , nak);
}
else if ((hcchar.b.eptype == EP_TYPE_CTRL)||
(hcchar.b.eptype == EP_TYPE_BULK))
{
/* re-activate the channel */
hcchar.b.chen = 1;
hcchar.b.chdis = 0;
USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[num]->HCCHAR, hcchar.d32);
}
pdev->host.HC_Status = HC_NAK;
}
而V2.1.0 版本的NAK 處理過(guò)程如下:
else if (hcint.b.nak)
{
if(hcchar.b.eptype == EP_TYPE_INTR)
{
UNMASK_HOST_INT_CHH (num);
USB_OTG_HC_Halt(pdev, num);
}
else if ((hcchar.b.eptype == EP_TYPE_CTRL)||
(hcchar.b.eptype == EP_TYPE_BULK))
{
/* re-activate the channel */
hcchar.b.chen = 1;
hcchar.b.chdis = 0;
USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[num]->HCCHAR, hcchar.d32);
}
pdev->host.HC_Status[num] = HC_NAK;
CLEAR_HC_INT(hcreg , nak);
}
????唯一的區(qū)別就是CLEAR_HC_INT(hcreg , nak)的位置,在V1.0.0 版本中對(duì)于CTRL 和BULK 端點(diǎn)的NAK 中斷沒(méi)有清除NAK,我們的芯片會(huì)因此產(chǎn)生多次IN 傳輸?shù)恼?qǐng)求,導(dǎo)致數(shù)據(jù)傳輸錯(cuò) 誤。改為V2.1.1 的寫法后傳輸正常。(注意HC_Status 在V2.1.0 是數(shù)組,在V1.0.0 是單個(gè)數(shù)據(jù),直接拷貝的話要去掉后面的[num])
B. USB 外設(shè)的工作頻率有限制
????描述:有最低工作頻率的要求,也就是APB1 分頻后的時(shí)鐘必須大于12MHz,比如HCLK 為56MHz,APB1 的最大分頻系數(shù)為4,56/4 = 14MHz,可以正常工作。
11. SPI
????1) 輸入與輸出配置要求(STM32 不需要如此要求)
????解決方法 :
????GD32 在使用SPI 時(shí),IO 的配置必須嚴(yán)格遵守主從模式下的輸入與輸出配置,而STM32 無(wú)此要求,相關(guān)代碼如下:主機(jī)模式下IO 配置(主機(jī)以SPI 為例):
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_7;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOA,&GPIO_InitStructure);
從機(jī)模式下IO 配置(從機(jī)以SPI2 為例):
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_15;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_Init(GPIOB,&GPIO_InitStructure);
????3) 在GD32 的SPI 的時(shí)鐘信號(hào),空閑狀態(tài)需要配置成高電平,以保證數(shù)據(jù)的穩(wěn)定性,具體代碼如下
????解決方法
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
????4) 當(dāng)作為從機(jī)時(shí),在GD32 中,時(shí)鐘信號(hào)必須為8 的整數(shù)倍。
????解決方法
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
????5) 在GD32 中,不能使用SPI_I2S_FLAG_BSY 該位來(lái)判斷SPI 總線數(shù)據(jù)是否接收或發(fā)送完成。
12. 看門狗
????1) 進(jìn)入STOP 模式前打開看門狗,通過(guò)RTC 的ALR 喚醒后,程序會(huì)不斷被復(fù)位的現(xiàn)像
????描述:IWDG 內(nèi)部有個(gè)Reload 信號(hào),KEY 寄存器寫AAAA 會(huì)使其拉高,過(guò)一段時(shí)間自動(dòng)拉低。在拉底之前進(jìn)入STOP 狀態(tài)會(huì)使Reload 信號(hào)一直為高,等到退出STOP 后也保持為高,之后再寫AAAA 沒(méi)有辦法讓Reload 產(chǎn)生上升沿,也就沒(méi)辦法更新計(jì)數(shù)器了。
????解決方法:進(jìn)STOP 之前不要Reload,也可以調(diào)整下程序的順序,把IWDG 的配置放到RTC配置之前,效果是一樣的。
總結(jié)
以上是生活随笔為你收集整理的GD32 使用stm32 固件库的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 刷机精灵Android版V3.0,刷机精
- 下一篇: ansible 配置文件优先级