今天下午我期盼已久的星空派GD32F303终于收到了。这名字起的好,我突然想到周星驰的《逃学威龙 》里面的“星星派 ”。~!~
废话不多说,开箱照:
竟然是纸袋~
白色包装盒,印个LOGO也好啊~
被泡沫袋子包着,边上白色小盒是 电源线盒,显然已经被压扁了~
板子正面,布线紧密简洁美观~
板子背面:
电源线:
好了,开箱就到这~
下面我们开始整理GD32D303的开发环境,我们使用MDK开发~
先安装MDK器件支持PACK:
把官方给的资料打开,具有路径如下图,安装PACK~
随意打开一个工程:
点开魔术棒,第一项device,我们看到我们选择的芯片是GD32F303,
那么PACK就装好了~
我们用JLINK调试下载,把JLINK接收 开发板,同时USB端接上电脑~
点解DEBUG查看,发现器件ID号识别出来了,那就是连接好了~
我们把下载选项里面的擦除所有,改成擦除选择~
官方例子的结构,可能不符合个人习惯,我们把它按照原子 STM32的架构更改下,
由于我就是从原子STM32入门的,很习惯他的架构:
我们添加位带功能,我们先查看GPIO的读写寄出器地址:
我们编写代码:
- //IO口操作宏定义
- #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
- #define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
- #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
- //IO口地址映射
- #define GPIOA_BASE (GPIO_BASE + 0x00000000U)
- #define GPIOB_BASE (GPIO_BASE + 0x00000400U)
- #define GPIOC_BASE (GPIO_BASE + 0x00000800U)
- #define GPIOD_BASE (GPIO_BASE + 0x00000C00U)
- #define GPIOE_BASE (GPIO_BASE + 0x00001000U)
- #define GPIOF_BASE (GPIO_BASE + 0x00001400U)
- #define GPIOG_BASE (GPIO_BASE + 0x00001800U)
- #define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x40020014
- #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40020414
- #define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x40020814
- #define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x40020C14
- #define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x40021014
- #define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40021414
- #define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40021814
- #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40020010
- #define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40020410
- #define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40020810
- #define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40020C10
- #define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40021010
- #define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40021410
- #define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40021810
- //IO口操作,只对单一的IO口!
- //确保n的值小于16!
- #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
- #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入
- #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
- #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入
- #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出
- #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入
- #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
- #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入
- #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
- #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入
- #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出
- #define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入
- #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出
- #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入
复制代码
官方程序里面延时是ms级别的,且开启了SYSTICK中断。我们也用SYSTICK作为延时时基,但不开启中断,通过查询来实现:
我么们先看下Systick相关的时钟树:
看到为AHB_CLK/8,我们配置Systick的初始化代码:
选择时钟:
- //SYSTICK时钟选择
- #define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB)
- #define SysTick_CLKSource_HCLK ((uint32_t)0x00000004)
- #define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) ||
- ((SOURCE) == SysTick_CLKSource_HCLK_Div8))
- void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
- {
- /* Check the parameters */
- assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
- if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
- {
- SysTick->CTRL |= SysTick_CLKSource_HCLK;
- }
- else
- {
- SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
- }
- }
复制代码
- //初始化延迟函数
- //当使用OS的时候,此函数会初始化OS的时钟节拍
- //SYSTICK的时钟固定为AHB时钟/8
- //SYSCLK:系统时钟频率
- void delay_init(u8 SYSCLK)
- {
- SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//选择外部时钟 HCLK/8
- fac_us=SYSCLK/8; //不论是否使用OS,fac_us都需要使用
- fac_ms=(u16)fac_us*1000; //非OS下,代表每个ms需要的systick时钟数
- }
复制代码
us及ms延时函数:
- void delay_us(u32 nus)
- {
- u32 temp;
- SysTick->LOAD=nus*fac_us; //时间加载
- SysTick->VAL=0x00; //清空计数器
- SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
- do
- {
- temp=SysTick->CTRL;
- }while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
- SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
- SysTick->VAL =0X00; //清空计数器
- }
复制代码
- void delay_xms(u16 nms)
- {
- u32 temp;
- SysTick->LOAD=(u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit)
- SysTick->VAL =0x00; //清空计数器
- SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
- do
- {
- temp=SysTick->CTRL;
- }while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
- SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
- SysTick->VAL =0X00; //清空计数器
- }
- //延时nms
- //nms:0~65535
- void delay_ms(u16 nms)
- {
- u8 repeat=nms/540; //这里用540,是考虑到某些客户可能超频使用,
- //比如超频到248M的时候,delay_xms最大只能延时541ms左右了
- u16 remain=nms%540;
- while(repeat)
- {
- delay_xms(540);
- repeat--;
- }
- if(remain)delay_xms(remain);
- }
复制代码
下面我们配置调试串口USART0,可惜板上是232芯片,但是引脚留出了。我们外接一个USB转TTL模块,即可直接和电脑相连:
配置,及中断代码(接收结束以“rn”为标志):
- //初始化IO 串口1
- //bound:波特率
- void uart0_init(u32 bound)
- {
- /* 使能 GPIO 时钟 */
- rcu_periph_clock_enable(RCU_GPIOA);
- /* 使能 uart 时钟 */
- rcu_periph_clock_enable(RCU_USART0);
- /* 将GPIO A9 引脚复用为 USARTx_Tx */
- gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
- /* 将GPIO A10 引脚复用为 USARTx_Rx */
- gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
- /* USART 去初始化 */
- usart_deinit(USART0);
- //波特率设置
- usart_baudrate_set(USART0, 115200U);
- //接受使能
- usart_receive_config(USART0, USART_RECEIVE_ENABLE);
- //发送使能
- usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
- //使能串口0
- usart_enable(USART0);
- #if EN_USART0_RX
- /* 中断配置 */
- /* 使能串口中断 */
- nvic_irq_enable(USART0_IRQn, 0, 0);
- /* 使能 USART0 接收中断 */
- usart_interrupt_enable(USART0, USART_INT_RBNE);
- #endif
- }
- void USART0_IRQHandler(void) //串口0中断服务程序
- {
- u8 Res;
- #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
- OSIntEnter();
- #endif
- if(usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
- {
- Res =usart_data_receive(USART0);//读取接收到的数据
-
- if((USART0_RX_STA&0x8000)==0)//接收未完成
- {
- if(USART0_RX_STA&0x4000)//接收到了0x0d
- {
- if(Res!=0x0a)USART0_RX_STA=0;//接收错误,重新开始
- else USART0_RX_STA|=0x8000; //接收完成了
- }
- else //还没收到0X0D
- {
- if(Res==0x0d)USART0_RX_STA|=0x4000;
- else
- {
- USART0_RX_BUF[USART0_RX_STA&0X3FFF]=Res ;
- USART0_RX_STA++;
- if(USART0_RX_STA>(USART0_REC_LEN-1))USART0_RX_STA=0;//接收数据错误,重新开始接收
- }
- }
- }
- }
- #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
- OSIntExit();
- #endif
- }
复制代码
PRINTF重定向:
- //加入以下代码,支持printf函数,而不需要选择use MicroLIB
- #if 1
- #pragma import(__use_no_semihosting)
- //标准库需要的支持函数
- struct __FILE
- {
- int handle;
- };
- FILE __stdout;
- //定义_sys_exit()以避免使用半主机模式
- void _sys_exit(int x)
- {
- x = x;
- }
- //重定义fputc函数
- int fputc(int ch, FILE *f)
- {
- usart_data_transmit(USART0, (uint8_t)ch);
- while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
- return ch;
- }
- #endif
复制代码
到此,延时和串口调试函数就好了~我们可以输出语句了。
下面再配置LED,开箱怎么能少了LED呢~少了它就缺了灵魂。
我们用我们的位带操作缩短代码:
- #define LED0 PFout(0)// PF0
- #define LED1 PFout(1)// PF1
- #define LED2 PFout(2)// PF2
- #define LED3 PFout(3)// PF3
- void LED_Init(void)
- {
- //使能对应得时钟源
- rcu_periph_clock_enable(RCU_GPIOF);
- //配置引脚
- gpio_init(GPIOF, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
- //初始状态
- LED0=0;
- LED1=0;
- LED2=0;
- LED3=0;
- }
复制代码
好了,下面我们可以应用代码了。
我们等待串口输入,并将输出的语句输出,同时LED0定时闪烁~
- int main(void)
- {
- u16 t;
- u16 len;
- u16 times=0;
-
- delay_init(120);
- uart0_init(115200); //串口初始化为115200
- LED_Init();
- printf("FRE IS %drn",SystemCoreClock);
- while(1)
- {
- if(USART0_RX_STA&0x8000)
- {
- len=USART0_RX_STA&0x3fff;//得到此次接收到的数据长度
- printf("rn您发送的消息为:rnrn");
- for(t=0;t
- {
- usart_data_transmit(USART0, (uint8_t)USART0_RX_BUF[t]);//向串口0发送数据
- while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));//等待发送结束
- }
- printf("rnrn");//插入换行
- USART0_RX_STA=0;
- }else
- {
- times++;
- if(times%5000==0)
- {
- printf("rn星空派GD32F303开发板 串口实验rn");
- printf("qjp1988113@电子发烧友rnrn");
- }
- if(times%200==0)printf("请输入数据,以回车键结束n");
- if(times%30==0)LED0=!LED0;//闪烁LED,提示系统正在运行.
- delay_ms(10);
- }
- }
- }
复制代码
最终整理的工程结构如下:
编译下载,串口显示如下:
板子LED闪烁:
好了,开箱及第一个例程及DemoCode整理就到这了~
谢谢观看~
DemoCode代码:
0
|
|
|
|