苏州外发加工网,sem与seo的区别,烟台公司建网站,阿里云虚拟主机多个网站1、 系统 1) 晶振起振区别 描述#xff1a;启动时间#xff0c;GD32 与STM32 启动时间都是2ms#xff0c;实际上GD 的执行效率快#xff0c;所以ST 的HSE_STARTUP_TIMEOUT ((uint16_t)0x0500)是2ms#xff0c;但是这个宏定义值在GD 上时间就更加短了#xff0c;所以要加大… 1、 系统 1) 晶振起振区别 描述启动时间GD32 与STM32 启动时间都是2ms实际上GD 的执行效率快所以ST 的HSE_STARTUP_TIMEOUT ((uint16_t)0x0500)是2ms但是这个宏定义值在GD 上时间就更加短了所以要加大这个值的设置。 解决方法将宏定义 #define HSE_STARTUP_TIMEOUT ((uint16_t)0x0500) 修改为 #define HSE_STARTUP_TIMEOUT ((uint16_t)0xFFFF) 备注启动时间宏定义所在位置 1、在V3.X 的库其启动时间宏定义在stm32f10x.h 头文件中路径\..\Libraries\CMSIS\CM3。库版本的不同所在目录也有所不同 2、在V3.0 以前的库其启动时间宏定义在stm32f10x_rcc.c 源文件中(HSEStartUp_TimeOut)路径\..\Libraries\STM32F10x_StdPeriph_Driver\src。 2) 部分客户使用有源晶振出现问题在GD32F103 小容量产品发现会在MCU 的复位管脚一直把电平拉到0.89V电平不能保持在高电平。 描述是由于部分有源晶振起振时间太快复位信号还没有完成导致的 解决方法就是在有源晶振的输入端与地之前并上一个30pf电容。 3) GD32 MCU 主频支持108MHz 高性能在代码移植方面需要注意事项 描述GD32 通过芯片内部加大缓存提高了相同工作频率下的代码执行速度带来了高性能的使用体验。 解决方法因此如果代码有用到for 循环或while 循环语句做精确定时的定时时间会由于代码执行速度加快而使循环的时间变短。使用Timer 定时器则没有影响。 4) GD32F105/107 系列MCU 配置为108MHz 有何不同 描述通过Clock configuration register (RCC_CFGR) 中 第21 18 位为PLLMUL[3:0]再结合第29 位PLLMUL[4]组成5 位的位域来确定PLL 倍频系数即通过软件配置来定义PLL 的倍频系数且PLL 输出频率绝对不得超过最高主频(108MHz)。 2. 内部Flash 1) 芯片设置读保护用法 描述:由于GD 的Flash 是自己的专利技术STM 的Flash 是第三方提供的所以GD 的Flash 和STM 的Flash 有些许差异。GD 的擦除时间会长一点. 解决方法:在写完KEY 序列以后需要读该位确认key 已生效。 所以这里应该插入 While( ! (FLASH-CR 0x200 ) ); // Wait OPTWRE 或可简单插入两个NOP。 __NOP(); __NOP(); 在ST 库中只有 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) 四个函数需要修改。 2) IAP 在应用中编程 描述:GD32 由于自有flash 的0 访问时序同STM32 在Flash 的Erase 和Program 上存在差别GD32 的Erase 和Program 时间比STM32 的稍微长些,建议对Erase 和Program 时间进行修改。 解决方法:将宏定义 #define EraseTimeout ((uint32_t)0x000B0000) #define ProgramTimeout ((uint32_t)0x00002000) 修改为 #define EraseTimeout ((uint32_t)0x000FFFFF) #define ProgramTimeout ((uint32_t)0x0000FFFF) 备注 Erase 和Program 时间宏定义在stm32f10x_flash.c 源文件中 路径\..\Libraries\STM32F10x_StdPeriph_Driver\src 3) 用IAR 下载配置 解决方法:在批量生产的时候首先会烧写一个USB 的boot这个boot 自动运行后在由上位机软件进行烧写应用程序。如果boot 程序不能自动运行则需要重新插拔一次电源。给生产造成一些麻烦。产生不能自动运行程序的原因是如果程序设置读保护的话需要等待FLASH_CR 的第9[OPTWRE]位为1.如果没有置位的话继续执行就会出错。由于ST 的执行速度慢程序执行到读FLASH_CR 寄存器的时候该位已经置1GD 的执行速度比较快程序运行到这的时候该位还没置1因此需要在FLASH_ReadOutProtection 函数里面添加一些轮询该位为1 或者加一些延时。 3. ISP 烧写软件 1) ISP 烧写建议使用官方烧写软件 描述GD32 芯片内部flash 同STM32 有区别。 解决方法建议到www.mcuisp.com 下载最新版本的MCUISP。另外GD32 也有专门的烧写软件GigaDevice MCU ISP Programmer可以到http://bbs.21ic.com/gd32 论坛下载。如果使用自制的ISP 软件或脱机编程器实现ST 和GD 完全兼容建议修改以下参数 1、 页擦除等待超时时间增加至300ms,整片擦除等待超时时间增加至3s 左右。 2、 字编程等待超时时间增加至2ms页编程等等超时时间增加至300ms。 4.I/O 口 1) IO 口外部中断使用方法 描述在关闭期间如果外部引脚有电平的变化在使用IMR 打开中断后会马上进入中断服务程序。理论是打开中断前不管管脚是否有电平的变化都不会影响到打开后的中断响应。 解决方法所以解决方法就是通过禁用上升沿或者下降沿检测寄存器来开关中断不能使用IMR 屏蔽寄存器。程序如下 EXTI-FTSR ~EXTI_Line3; //关闭沿检测以达到关闭中断的目的下降沿使用FTSR 寄存器上升沿使用RTSR 寄存器 EXTI-PR EXTI_Line3; EXTI-FTSR | EXTI_Line3; 2) 在待机模式PA8 引脚特殊设置 描述在使用低功耗的情况下PA8 会被MCU 在内部被设置为地PA8 复用为MCU 内部频率输出超低功耗设置时需要悬空。 解决方法在待机模式PA8 悬空不用。 3) 低功耗下必须注意 描述在使用低功耗情况下把软件全部端口A-F时钟关掉无论是否有该端口。 4) 当有脉冲群冲击管脚 描述需要在在进入中断后关闭中断。 5. 定时器 1) 定时器输入捕获模式需要软件清中断 描述STM 定时器输入捕获模式默认能硬件清中断GD 为了更加严格要求配置需要做软件清中断 。 解决方法软件清除标志位。 2) 定时器向上脉冲计数模式设置 描述定时器的用法差异。 解决方法脉冲计数模式下装载值必须设置为比预期值大否则不计数在ST 上如果重载值不设置初始为0的时候CNT 可以正常计数。 在GD 上如果重载值不设置保持初始为0 的时候会因为重载值为零即便是来一个脉冲也会导致所有的寄存器复位从而不能正常计数。 3) TIM、ADC 模块 描述Timer、ADC 模块的触发信号宽度要求。 解决方法由于内部有高速和低速两条外围总线Timer、ADC 模块和其他外设共同使用这两个总线。GD32F103/101 系列Flash 128KB 及以下的型号Timer、ADC 等模块识别触发信号的条件是触发信号宽度大于模块所在总线的时钟宽度。 6. 串口USART 1) USART 连续发送数据字节有空闲位 描述字节间有空闲位。 解决方法对于一般的通讯来说不会有影响只对于一般在通讯上有特殊协议的才会产生数据不准确的情况所以特定情况修改程序。 7. I2C 总线 1) 硬件I2C 特殊配置 描述GD 的I2C 相对STM 的来说要少一个标志位 解决方法 1、宏地址定义改变 #define I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED ((uint32_t)0x00060002) #define I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ((uint32_t)0x00070002) 2、硬件I2C 在会在向从机发送7bits 地址完成后从机还没来得及识别。看客户应用)我们可以在发送完7bits 后加个延时让从机完全识别 I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter); { int i 0xfff; while(i --); } 3、检测ADDR 不能使用I2C_CheckEvent 函数因为他会清除ADDR可以使用I2C_GetFlagStatus 函数。 就是把while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); 改为while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR)); 4、还有个关于编程步骤的严谨性跟STM 想比我们是先Clear_ACK,再Clear_ARRD。 8. ADC 采集 1) ADC 采样设置 描述:ADC 启动 解决方法: 1. 当ADON0 时写入1 后需要等待一段时间t_WAIT如果用ST 库的话就在ADC_CMD 后面加20us 左右的延时。 2. 如果采用中断获得采样数据后需要软件清除中断。 9. SDIO 1) SDIO DAT 3 pin 的在 1 bit bus mode 和4 bit bus mode 下的配置 描述: 1、 SDIO 在 1 bit bus mode 下DAT 3 pin 是低电平这样会导致 SD Card 进入SPI 模式。 原因初始化失败的原因主要是因为GD32 的芯片SDIO 的DAT3 口存在BUG。 2、 在4 位模式下通过上面的方法程序能正常初始化但不能正常读写SD卡。 原因因为DAT3 口在前面已经配置成推挽输出所以在4 位模式下不能正常读下。在调用4 位模式前把DAT3 的端口配置成复用推挽输入即可解决问题。 解决方法 1、 1 bit bus mode 的解决方法建议在SDIO 使能之前先把 SDIO DAT 3 pin 配置成推挽输出并且要置成高电平使 SDIO DAT 3 pin 保持高电平即可. 2、 4 bit bus mode 的解决方法在调用4 位模式前把DAT3 的端口配置成复用输出即可解决问题。 2) 程序在刚烧完后能正常读写SD 卡断电再上电后SD 卡初始化失败需要手动复位一次后才正常 描述 在某些SD 卡中GD32 断电再上电会引起SD 卡上的时钟信号不正常导致SD 卡发送命令失败。 解决方法:在程序中打开SD 卡时钟后增加一小段延时以保证SD 卡时钟信号稳定。这个延时添加的地方在sdcard.c(即SDIO 的配置文件中)然后在SD_Error SD_Init(void)这个函数中找到SDIO_DeInit();就在这个后面加个延时。 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE); SDIO_DeInit(); { int i 0xffff; while(i --); } 10. USB A. USB_OTG 1) 客户使用STM32 的DFU 原工程时需要注意几点 解决方法 1、 在usb_istr.c 中增加如下语句 for (i0;i8;i) EP[i] _GetENDPOINT(i); for (i0;i8;i) _SetENDPOINT(i, EP[i] 0x7070); 2、 在usb_conf.h 中按照下图红色字体语句进行修改 #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、 把固件库中的stm32f10x_flash.c 使用附件的进行替换。 4、 软件进行读保护位时需要选使用FLASH_Unlock();函数 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 个端点数组越界导致Itf_Desc 被清空所以主机不能识别设备类型。USBH_conf.h 文件的USBH_MAX_NUM_ENDPOINTS 的定义由2 改成3 就可以了将#define USBH_MAX_NUM_ENDPOINTS 2 改为#define USBH_MAX_NUM_ENDPOINTS 3 2. 在In 端点中断处理程序USB_OTG_USBH_handle_hc_n_In_ISR 中对于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 处理过程如下 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); } 唯一的区别就是CLEAR_HC_INT(hcreg , nak)的位置在V1.0.0 版本中对于CTRL 和BULK 端点的NAK 中断没有清除NAK我们的芯片会因此产生多次IN 传输的请求导致数据传输错 误。改为V2.1.1 的写法后传输正常。(注意HC_Status 在V2.1.0 是数组在V1.0.0 是单个数据直接拷贝的话要去掉后面的[num] B. USB 外设的工作频率有限制 描述有最低工作频率的要求也就是APB1 分频后的时钟必须大于12MHz比如HCLK 为56MHzAPB1 的最大分频系数为456/4 14MHz可以正常工作。 11. SPI 1) 输入与输出配置要求STM32 不需要如此要求 解决方法 GD32 在使用SPI 时IO 的配置必须严格遵守主从模式下的输入与输出配置而STM32 无此要求相关代码如下主机模式下IO 配置主机以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); 从机模式下IO 配置从机以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 的时钟信号空闲状态需要配置成高电平以保证数据的稳定性具体代码如下 解决方法 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) 当作为从机时在GD32 中时钟信号必须为8 的整数倍。 解决方法 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 该位来判断SPI 总线数据是否接收或发送完成。 12. 看门狗 1) 进入STOP 模式前打开看门狗通过RTC 的ALR 唤醒后程序会不断被复位的现像 描述IWDG 内部有个Reload 信号KEY 寄存器写AAAA 会使其拉高过一段时间自动拉低。在拉底之前进入STOP 状态会使Reload 信号一直为高等到退出STOP 后也保持为高之后再写AAAA 没有办法让Reload 产生上升沿也就没办法更新计数器了。 解决方法进STOP 之前不要Reload也可以调整下程序的顺序把IWDG 的配置放到RTC配置之前效果是一样的。