本帖最后由 jinyi7016 于 2016-4-6 09:52 编辑
这里吐槽一下,这么大的144的芯片就引出了这么几个引脚,太浪费了,就算要跟ardunio看齐,除了引脚,好像也没有什么其他可以与ardunio相关联了吧。 那几个LED布线拉了好长,还是沿板子最边上走的线,就近找个位置放一下也可以吧。
先上最后的组成图。
下载F207相关文件。
下载GD-Link等等驱动。
下载Keil 5.13以上的版本,可以支持GD32F2xx的芯片。 前面已经下载了GD32F2xx的pack包,打开keil5,选择这个图标打开pack installer。
选择FileàImport… 再选择上Keil.GD32F2xx_DFP.1.0.0.pack进行安装。 安装完成后就可以找到GD32F207的芯片型号了。
新建工程。 ProjectàNew uVision Project 输入工程名,选择芯片型号为GD32F207ZE。
进行Target设置,在Debug窗口选择仿真的型号如下图:
GD32F2xx的源码在GD32F20x_Firmware_Library.rar里,要提前下载的。
添加头文件目录:
编译完成,没有错误:
为了提高编译速度,可以把源码编译成lib:
从启动文件中可以看到,已经在s文件中调用了系统的初始化函数,所以在我们的main函数中是不用再次调用的。
插上开发板,识别了驱动,在keil里,看到了仿真器的信息。
GPIO试水: 光盘里没有找到原理图,只是有个硬件手册;从手册上看到LED的GPIO号
GPIO配置:
RCC_APB2PeriphClock_Enable函数,使能时钟。 使用GPIO_InitPara结构体,GPIO模式、速度、引脚号设置。 GPIO_Init函数初始化引脚。
GPIO_SetBits函数,把GPIO置高电平。 GPIO_ResetBits函数,把GPIO置低电平。
程序如下: #include "main.h"
#define LED1(a) if (a) \
GPIO_SetBits(GPIOD,GPIO_PIN_11);\
else \
GPIO_ResetBits(GPIOD,GPIO_PIN_11)
#define LED2(a) if (a) \
GPIO_SetBits(GPIOD,GPIO_PIN_12);\
else \
GPIO_ResetBits(GPIOD,GPIO_PIN_12)
#define LED3(a) if (a) \
GPIO_SetBits(GPIOD,GPIO_PIN_13);\
else \
GPIO_ResetBits(GPIOD,GPIO_PIN_13)
void GPIO_Configuration(void)
{
GPIO_InitPara GPIO_InitStructure;
RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_GPIOD,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_50MHZ;
GPIO_Init(GPIOD,&GPIO_InitStructure);
}
int main(void)
{
GPIO_Configuration();
SysTick_Configuration();
while (1){
LED1(1);
LED2(1);
LED3(1);
Delay_1ms(1000);
LED1(0);
LED2(0);
LED3(0);
Delay_1ms(1000);
LED1(1);
Delay_1ms(1000);
LED2(1);
LED1(0);
Delay_1ms(1000);
LED3(1);
LED2(0);
Delay_1ms(1000);
LED3(0);
Delay_1ms(1000);
}
}
程序烧写后,三个灯开始闪烁,但是有一个问题。在keil中配置成烧写后复位但是并没有效果。还是要按一次复位按键。
可以看出与STM32的使用方法是一样的,这样移植起来就不会有什么困难了。 通过以上的试验,可以确定GD32的开发与STM32是基本相通的,那么接下来就是做一下原有项目的移植了。
串口的使用配置:
UART1通过 CH340 芯片,转 USB 接口连接 PC。 原理图部分如下:
串口使用的两个引脚是PB6、PB7,那么要对这两个引脚进行初始化:
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_6 ;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_50MHZ;
GPIO_Init( GPIOB , &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_7;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_IN_FLOATING;;
GPIO_Init( GPIOB , &GPIO_InitStructure);
GPIO_PinRemapConfig(GPIO_REMAP_USART1, ENABLE);
之后就是对串口1的配置: 波特率选择的是115200,数据是8位,1个停止位,无校验。
USART_InitStructure.USART_BRR = 115200;
USART_InitStructure.USART_WL = USART_WL_8B;
USART_InitStructure.USART_STBits = USART_STBITS_1;
USART_InitStructure.USART_Parity = USART_PARITY_RESET;
USART_InitStructure.USART_HardwareFlowControl = USART_HARDWAREFLOWCONTROL_NONE;
USART_InitStructure.USART_RxorTx = USART_RXORTX_RX | USART_RXORTX_TX;
USART_Init(USART1, &USART_InitStructure);
/* USART enable */
USART_Enable(USART1, ENABLE);
USART_INT_Set(USART1, USART_INT_RBNE, ENABLE);
/* Enable the USARTx Interrupt */
NVIC_InitStructure.NVIC_IRQ = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQPreemptPriority = 0;
NVIC_InitStructure.NVIC_IRQSubPriority = 0;
NVIC_InitStructure.NVIC_IRQEnable = ENABLE;
NVIC_Init(&NVIC_InitStructure);
这里使用了串口1 的接收中断,从启动文件中可以找到,中断函数的名字是USART1_IRQHandler,在gd32F20x_it.c中新建这个函数。
先实现了最简单的loopback功能的中断服务函数:
void USART1_IRQHandler(void)
{
unsigned int temp;
if(USART_GetIntBitState(USART1, USART_INT_RBNE) != RESET)
{
temp=USART_DataReceive(USART1);
USART_DataSend(USART1, temp);
}
if(USART_GetIntBitState(USART1, USART_INT_TBE) != RESET)
{
USART_INT_Set(USART1, USART_INT_TBE, DISABLE);
}
}
定时器:
定时器的使用也是项目中所必须的。 对于GD32F207的定时器的定时功能与中断功能,没有在例程中找到,自己参考STM32写的。
首先是对定时器的配置: 使定时器2缺省状态。通过结构体TIM_TimeBaseStructure对定时器2初始化化。
TIMER_DeInit(TIMER2);
TIM_TimeBaseStructure.TIMER_Prescaler = 119;
TIM_TimeBaseStructure.TIMER_CounterMode = TIMER_COUNTER_UP;
TIM_TimeBaseStructure.TIMER_Period = 999;
TIM_TimeBaseStructure.TIMER_ClockDivision = TIMER_CDIV_DIV1;
TIM_TimeBaseStructure.TIMER_RepetitionCounter = 1;
TIMER_BaseInit(TIMER2,&TIM_TimeBaseStructure);
TIMER_INTConfig(TIMER2,TIMER_INT_UPDATE,ENABLE);
TIMER_CARLPreloadConfig(TIMER1,ENABLE);
/* TIMER enable counter*/
TIMER_Enable( TIMER2, ENABLE );
中断配置: 这是参考STM32写的,与STM32的库函数有一些区别。 NVIC_InitStructure.NVIC_IRQ = TIMER2_IRQn;
NVIC_InitStructure.NVIC_IRQPreemptPriority = 1;
NVIC_InitStructure.NVIC_IRQSubPriority = 1;
NVIC_InitStructure.NVIC_IRQEnable = ENABLE;
NVIC_Init(&NVIC_InitStructure);
注意要添加中断服务函数。函数名与启动文件中的要一样。
SPI: SPI 是与电能计量芯片通讯的,电压、电流、电能都是通过SPI口从电能计量芯片是读取出来的,这一部分也是很重要的。 电能计量芯片选用ATT7022E,它适用于三相三线和三相四线应用。ATT7022E集成了多路二阶sigma-deltaADC、参考电压电路以及所有功率、能量、有效值、功率因数及频率测量的数字信号处理等电路,能够测量各相以及合相的有功功率、无功功率、视在功率、有功能量及无功能量,同时还能测量各相电流、电压有效值、功率因数、相角、频率等参数,充分满足三相复费率多功能电能表的需求。详细数据定义请参阅参数寄存器部分。
ATT7022E与GD32F207的接线图为:
那么从数据手册中,找到SPI1对应的引脚,使用PA4作为片选CS引脚。
这四个引脚在板子上对应的位置为:
接下来就是在程序上对SPI1进行配置了。 首先是GPIO的配置: void SPI1_GPIO_Configuration(void)
{
GPIO_InitPara GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_5 |GPIO_PIN_7;
GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_50MHZ;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_6 ;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_4;
GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_50MHZ;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
与STM32不同的是,在STM32中,SCLK、MOSI、MISO都配置成了GPIO_Mode_AF_PP,但是GD32的MISO却是GPIO_MODE_IN_FLOATING。
对SPI的配置如下: SPI_InitPara SPI_InitStructure;
SPI_InitStructure.SPI_TransType = SPI_TRANSTYPE_FULLDUPLEX;
SPI_InitStructure.SPI_Mode = SPI_MODE_MASTER;
SPI_InitStructure.SPI_FrameFormat = SPI_FRAMEFORMAT_8BIT;
SPI_InitStructure.SPI_SCKPL = SPI_SCKPL_LOW;
SPI_InitStructure.SPI_SCKPH = SPI_SCKPH_1EDGE;
SPI_InitStructure.SPI_SWNSSEN = SPI_SWNSS_SOFT;
SPI_InitStructure.SPI_PSC = SPI_PSC_64;
SPI_InitStructure.SPI_FirstBit = SPI_FIRSTBIT_MSB;
SPI_InitStructure.SPI_CRCPOL = 7;
SPI_Init(SPI1, &SPI_InitStructure);
SPI_Enable(SPI1, ENABLE);
有好多的宏定义也STM32的,与GD32F103的都不同了,要移植原有的程序,还是要再费点功夫的。 使用查询对SPI进行字节读写的程序: while(SPI_I2S_GetBitState(SPI3, SPI_FLAG_TBE) == RESET);
SPI_I2S_SendData(SPI3,data);
while (SPI_I2S_GetBitState(SPI3, SPI_FLAG_RBNE) == RESET);
return SPI_I2S_ReceiveData(SPI3);
接下来就是对ATT7022E的操作了,要读取ATT7022E中的数据,也要向ATT7022E中写入数据时行配置,使ATT7022E能正常的工作。那么最基本的就是对ATT7022E的寄存器进行读写了。 以下是ATT7022E的SPI读取数据的时序图,先发送8位的寄存器地址,再接收24位的寄存器数据。由于ATT7022E的数据寄存器是24位的,所以读取时是按32位数据进行处理的,最高8位为0。
对应的程序为:
union{unsigned char bit[4];unsigned int all;}temp;
ATT7022E_CS(0);
SPI3_ReadWritebit(addr);
temp.bit[3]=0;
temp.bit[2]=SPI3_ReadWritebit(0);//H
temp.bit[1]=SPI3_ReadWritebit(0);
temp.bit[0]=SPI3_ReadWritebit(0);//L
ATT7022E_CS(1);
return temp.all;
以下是ATT7022E的写寄存器的时序图,先发送8位的寄存器地址,再发送16位的寄存器数据。这里是ATT手册的错误,它的配置寄存器都是16位的,这里只要发送16位的寄存器数据就可以了。
对应的程序为: union{unsigned char bit[2];unsigned short int all;}temp;
temp.all=data;
ATT7022E_CS(0);
SPI3_ReadWritebit(addr);
SPI3_ReadWritebit(0x00);
SPI3_ReadWritebit(temp.bit[1]);
SPI3_ReadWritebit(temp.bit[0]);
ATT7022E_CS(1);
对ATT7022E配置时,最好是关掉中断,等配置完成了再打开中断,防止配置过程中出现问题,导致ATT7022E工作不正常。
TIMER_INTConfig(TIMER2,TIMER_INT_UPDATE,DISABLE);
USART_INT_Set(USART1, USART_INT_RBNE, DISABLE);
楼下继续......
|