首先,再次感谢21IC给了我关于GDF207ZE的试用机会,关于GD32F207的详细介绍,详情可以参照我的上一个帖子:
【试用】 国产MCU神作GD207ZE——开箱篇!
https://bbs.21ic.com/forum.php?mo ... amp;fromuid=1428042
好了,废话不多说,接下来开始我们关于GD32F207的第一程序的开发吧。
参考了关于这颗芯片的相关手册,发现跟STM32的很多架构,寄存器都很通用,因此,希望对于以前关于stm32的例程就很容易可以移植了,这里,我借用了以前写过的驱动,在GD板子上进行一些简易的移植,这里,主要用的是DHT11跟ADC模块,然后主要通过串口输出信息,以看到相关的测量结果~
简单描述一下实现过程:
1.数字温湿度传感器DHT11采用单总线输出数据,单次数据包共5Byte(40bit),包括先发送高位,数据格式为:湿度整数+湿度小数+温度整数+温度小数+校验和,各占1 Byte,校验和为前4个Byte相加,由此可计算出温湿度的数值。
DHT11通讯过程的时序图如下图所示,空闲状态时总线为高电平,MCU发送开始信号,拉低总线等待DHT11响应(至少18ms),之后拉高总线20~40μs;DHT11接收到开始信号,在其结束后发送80μs的低电平响应信号,之后拉高总线40~50μs,再拉低40~50μs,接着输出数据;主机读取到响应信号后开始接收数据;一次数据传输完成,DHT11拉低总线50μs,之后总线进入空闲状态。 相关的操作手册在DHT11的数据手册里面已经详细提及到了,感兴趣的朋友可以去下载来看看,这里不再多说了!
下面请上我们的驱动代码:
相关的驱动相信大家也很熟悉啦,这里是引用了原子哥的驱动来移植的,感谢原子哥~
同时,还有ADC 部分的驱动代码:
- #include "adc.h"
- #include "delay.h"
- //初始化ADC
- void Adc_Init(void)
- {
- ADC_InitPara ADC_InitStructure;
- GPIO_InitPara GPIO_InitStructure;
- RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_GPIOA | RCC_APB2PERIPH_ADC1, ENABLE ); //使能ADC1通道时钟
- RCC_ADCCLKConfig(RCC_ADCCLK_APB2_DIV6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
- //PA1、PA2作为模拟通道输入引脚
- GPIO_InitStructure.GPIO_Pin = GPIO_PIN_1 | GPIO_PIN_2;
- GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AIN; //模拟输入引脚
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- ADC_InitStructure.ADC_Mode = ADC_MODE_INDEPENDENT; //ADC工作模式:ADC1工作在独立模式
- ADC_InitStructure.ADC_Mode_Scan = DISABLE; //模数转换工作在单通道模式
- ADC_InitStructure.ADC_Mode_Continuous = DISABLE; //模数转换工作在单次转换模式
- ADC_InitStructure.ADC_Trig_External = ADC_EXTERNAL_TRIGGER_MODE_NONE; //转换由软件而不是外部触发启动
- ADC_InitStructure.ADC_Data_Align = ADC_DATAALIGN_RIGHT; //ADC数据右对齐
- ADC_InitStructure.ADC_Channel_Number = 2; //顺序进行规则转换的ADC通道的数目
- ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
-
- ADC_Enable(ADC1,ENABLE);
- ADC_Calibration(ADC1);
- }
- //获得ADC值
- //ch:通道值 0~3
- uint16_t Get_Adc(uint8_t ch)
- {
- //设置指定ADC的规则组通道,一个序列,采样时间
- ADC_RegularChannel_Config(ADC1,ch,1,ADC_SAMPLETIME_239POINT5); //ADC1,ADC通道,采样时间为239.5周期
-
- ADC_SoftwareStartConv_Enable(ADC1,ENABLE); //使能指定的ADC1的软件转换启动功能
-
- while(ADC_GetBitState(ADC1,ADC_FLAG_EOC)!=SET);//等待转换结束
- return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
- }
- float Get_Adc_Average(uint8_t ch,uint8_t times)
- {
- uint32_t temp_val=0;
- uint8_t t;
- for(t=0;t<times;t++)
- {
- temp_val+=Get_Adc(ch);
- delay_ms(5);
- }
- return (float)temp_val/times* (3.3 / 4096.0);
- }
分别读取ADC1的ADC_IN1和ADC_IN2的转换值,取3次的平均值后转换为0-3.3V电压值发送到PC。
USART发送程序采用colibri_bsp_uart.c中的EvbUart1Printf(char* fmt, ...)函数,该函数实现了printf()的功能,按照printf()的格式调用即可。
硬件接线如下:
PG8:DHT11 DATA
PA1:电位器1
PA2:电位器2
PB6:USART1 TX
其次,在对于DHT11的操作中,最为重要的还是延时函数的精确性:
其中用到的延时函数采用cortex-M3内核中的跟踪组件DWT的时钟周期计数CYCCNT实现:
- #include "delay.h"
- #define DWT_CR *(volatile u32 *)0xE0001000
- #define DWT_CYCCNT *(volatile u32 *)0xE0001004
- #define DEM_CR *(volatile u32 *)0xE000EDFC
- #define DEM_CR_TRCENA (1 << 24)
- #define DWT_CR_CYCCNTENA (1 << 0)
- static uint32_t cpuclkfeq;
- void delay_init(uint32_t clk)
- {
- cpuclkfeq = clk;
- DEM_CR |= DEM_CR_TRCENA;
- // DWT_CYCCNT = 0u;
- DWT_CR |= DWT_CR_CYCCNTENA;
- }
- void delay_us(uint32_t us)
- {
- uint32_t temp;
- temp= DWT_CYCCNT;
- us *= SystemCoreClock/1000000;
- while((uint32_t)( DWT_CYCCNT - temp)< us);
- }
- //void delay_us(uint32_t value)
- //{
- // uint32_t i;
- // i = value * 15;
- // while(i--);
- //}
- void delay_ms(uint32_t ms)
- {
- uint32_t temp;
- temp= DWT_CYCCNT;
- ms *= SystemCoreClock/1000;
- while((uint32_t)( DWT_CYCCNT - temp)< ms);
- }
综上,将代码工程编译通后,通过GD-LINK连接到电脑进行下载:
运行结果如下:
下面再附上代码文件,请大家轻喷~
GD32F207.zip
(3.97 MB, 下载次数: 30)
|