本帖最后由 qjp1988113 于 2021-7-30 16:26 编辑
基于ST的对应型号缺货,大家都纷纷测试国内的替代芯片,我也想试一把。看到GD32E230C8T6理论上可以替代STM32F103C8T6,在这次去X商城买料的
时候,我顺便买了片样片,并要了个免费的最新系统样板PCB。
到货后,马不停蹄开工,焊好~
焊好后,去官网下载资料:
MDK PACK:
GD32E23x_AddOn_V1.1.0.rar
(1.77 MB)
规格书:
GD32E230xx_Datasheet_Rev1.4.pdf
(2.44 MB)
用户手册:
GD32E23x_yonghushouce_Rev1.4.pdf
(8.4 MB)
固件手册:
GD32E23x_gujiankushiyongzhinan_Rev1.0.pdf
(5.69 MB)
BSP:
GD32E23x_Firmware_Library_V1.1.1.rar
(861.82 KB)
对应开发板资料:
GD32E23x_Demo_Suites_V1.0.1.rar
(4.06 MB)
为了放心,我还是粗略的看了下它的规格书:
主要描述(除了内核M23,其他外设几乎没啥变动)
当前选用的C8T6(容量还是跟ST的保持一致,国产的就不能大些么~)
引导模式:
其中有一点不一样的就是,它的BOOT1由原来的映射引脚,变成了寄存器的一个配置位!
我们用跳帽把BOOT0连到GND,选择内部FLASH启动~
//////////////////////////////////////////////////////////////
我们看下我们最小系统的原理图:
不能再简陋了,就是最小系统加4个LED,2个KEY(其中只有WAKEUP能编程用)。
我们连接它的串口,好让调试信息输出:
查看数据手册得:
还是PA9/PA10与ST的一样。
我们打开GD32E23x_Demo_Suites_V1.0.1\GD32E230C_EVAL_Demo_Suites,这个板型号跟我的最新系统一致,就用
它的程序进行更改:
我们发现在它的gd32e230c_eval文件里,几乎包含了我们想要的外设,但是引脚有少许差异,修改下:
/*!
\file gd32e230c_eval.h
\brief definitions for GD32E230C_EVAL's leds, keys and COM ports hardware resources
\version 2019-02-19, V1.0.0, firmware for GD32E23x
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef GD32E230C_EVAL_H
#define GD32E230C_EVAL_H
#ifdef cplusplus
extern "C" {
#endif
#include "gd32e23x.h"
/* exported types */
typedef enum
{
LED1 = 0,
LED2 = 1,
LED3 = 2,
LED4 = 3
}led_typedef_enum;
typedef enum
{
KEY_WAKEUP = 0,
//KEY_TAMPER = 1,
}key_typedef_enum;
typedef enum
{
KEY_MODE_GPIO = 0,
KEY_MODE_EXTI = 1
}keymode_typedef_enum;
/* eval board low layer led */
#define LEDn 4U
#define LED1_PIN GPIO_PIN_10
#define LED1_GPIO_PORT GPIOB
#define LED1_GPIO_CLK RCU_GPIOB
#define LED2_PIN GPIO_PIN_11
#define LED2_GPIO_PORT GPIOB
#define LED2_GPIO_CLK RCU_GPIOB
#define LED3_PIN GPIO_PIN_8
#define LED3_GPIO_PORT GPIOA
#define LED3_GPIO_CLK RCU_GPIOA
#define LED4_PIN GPIO_PIN_9
#define LED4_GPIO_PORT GPIOA
#define LED4_GPIO_CLK RCU_GPIOA
/* eval board low layer button */
#define KEYn 1U //2U
/* wakeup push-button */
#define WAKEUP_KEY_PIN GPIO_PIN_0
#define WAKEUP_KEY_GPIO_PORT GPIOA
#define WAKEUP_KEY_GPIO_CLK RCU_GPIOA
#define WAKEUP_KEY_EXTI_LINE EXTI_0
#define WAKEUP_KEY_EXTI_PORT_SOURCE EXTI_SOURCE_GPIOA
#define WAKEUP_KEY_EXTI_PIN_SOURCE EXTI_SOURCE_PIN0
#define WAKEUP_KEY_EXTI_IRQn EXTI0_1_IRQn
/* tamper push-button */
//#define TAMPER_KEY_PIN GPIO_PIN_13
//#define TAMPER_KEY_GPIO_PORT GPIOC
//#define TAMPER_KEY_GPIO_CLK RCU_GPIOC
//#define TAMPER_KEY_EXTI_LINE EXTI_13
//#define TAMPER_KEY_EXTI_PORT_SOURCE EXTI_SOURCE_GPIOC
//#define TAMPER_KEY_EXTI_PIN_SOURCE EXTI_SOURCE_PIN13
//#define TAMPER_KEY_EXTI_IRQn EXTI4_15_IRQn
/* eval board low layer COM */
#define COMn 1U
/* definition for COM, connected to USART0 */
#define EVAL_COM USART0
#define EVAL_COM_CLK RCU_USART0
#define EVAL_COM_TX_PIN GPIO_PIN_9
#define EVAL_COM_RX_PIN GPIO_PIN_10
#define EVAL_COM_GPIO_PORT GPIOA
#define EVAL_COM_GPIO_CLK RCU_GPIOA
#define EVAL_COM_AF GPIO_AF_1
/* function declarations */
/* configure led GPIO */
void gd_eval_led_init(led_typedef_enum lednum);
/* turn on selected led */
void gd_eval_led_on(led_typedef_enum lednum);
/* turn off selected led */
void gd_eval_led_off(led_typedef_enum lednum);
/* toggle the selected led */
void gd_eval_led_toggle(led_typedef_enum lednum);
/* configure key */
void gd_eval_key_init(key_typedef_enum keynum, keymode_typedef_enum keymode);
/* return the selected key state */
uint8_t gd_eval_key_state_get(key_typedef_enum keynum);
/* configure COM port */
void gd_eval_com_init(uint32_t com);
#ifdef cplusplus
}
#endif
#endif /* GD32E230C_EVAL_H */
main函数修改如下:
/*!
\file main.c
\brief running LED
\version 2019-02-19, V1.0.0, firmware for GD32E23x
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32e23x.h"
#include "gd32e230c_eval.h"
#include "systick.h"
#include <stdio.h>
/*!
\brief main function
\param[in] none
\param[out] none
\retval none
*/
int main(void)
{
//时钟初始化
systick_config();
//初始化LED
gd_eval_led_init(LED1);
gd_eval_led_init(LED2);
gd_eval_led_init(LED3);
gd_eval_led_init(LED4);
gd_eval_led_off(LED1);
gd_eval_led_off(LED2);
gd_eval_led_off(LED3);
gd_eval_led_off(LED4);
//初始化按键
gd_eval_key_init(KEY_WAKEUP,KEY_MODE_GPIO);
//初始化串口0
gd_eval_com_init(EVAL_COM);
while(gd_eval_key_state_get(KEY_WAKEUP)==SET)
{
printf("please press wakeup_key to continue!\r\n");
delay_1ms(200);
}
while(1){
/* turn on LED1, turn off LED4 */
gd_eval_led_on(LED1);
gd_eval_led_off(LED4);
delay_1ms(1000);
/* turn on LED2, turn off LED1 */
gd_eval_led_on(LED2);
gd_eval_led_off(LED1);
delay_1ms(1000);
/* turn on LED3, turn off LED2 */
gd_eval_led_on(LED3);
gd_eval_led_off(LED2);
delay_1ms(1000);
/* turn on LED4, turn off LED3 */
gd_eval_led_on(LED4);
gd_eval_led_off(LED3);
delay_1ms(1000);
}
}
/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
usart_data_transmit(USART0, (uint8_t) ch);
while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
return ch;
}
编译下载,查看现象:
按下WAKEUP键后,继续执行到WHILE里面:
LED轮流亮灭~
上面仅仅实现了串口的打印,下面我们开启串口的接收中断,并将接收到的指令发回:在之前的串口初始化代码下面,我们定义2个宏,分别代表开启接收中断和发送中断:
#define EN_USART0_RX 1 //使能(1)/禁止(0)串口0接收中断
#define EN_USART0_TX 0 //使能(1)/禁止(0)串口0发送中断
发送中断一般很少用,我们开启接收中断。关闭发送中断:
#if EN_USART0_RX //如果使能了接收
//使能接收中断
usart_interrupt_enable(USART0, USART_INT_RBNE);
/* USART interrupt configuration */
nvic_irq_enable(USART0_IRQn, 0);
#endif
使能接收中断,并开启串口中断。
下面我们开始写接收中断的函数:
void USART0_IRQHandler(void) //串口1中断服务程序
{
#if EN_USART0_RX
uint8_t Res;
if(usart_interrupt_flag_get(EVAL_COM, USART_INT_FLAG_RBNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =usart_data_receive(EVAL_COM); //读取接收到的数据
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;//接收数据错误,重新开始接收
}
}
}
}
#endif
#if EN_USART0_TX
if(usart_interrupt_flag_get(EVAL_COM, USART_INT_FLAG_TBE)!= RESET)
{
/* transmit data */
// usart_data_transmit(EVAL_COM, transmitter_buffer[txcount++]);
// if(txcount == transfersize){
// usart_interrupt_disable(EVAL_COM, USART_INT_TBE);
// }
}
#endif
}
之前的printf重定义,仍然保留:
/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
usart_data_transmit(USART0, (uint8_t) ch);
while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
return ch;
}
具体串口代码:
usart0.h
#ifndef __USART0_H
#define __USART0_H
#include "stdio.h"
#include "gd32e23x.h"
#include "gd32e230c_eval.h"
#include "systick.h"
#define USART0_REC_LEN 200 //定义最大接收字节数 200
#define EN_USART0_RX 1 //使能(1)/禁止(0)串口0接收中断
#define EN_USART0_TX 0 //使能(1)/禁止(0)串口0发送中断
extern uint8_t USART0_RX_BUF[USART0_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern uint16_t USART0_RX_STA; //接收状态标记
void uart0_init(uint32_t bound);
#endif
usart0.c
#include "usart0.h"
uint8_t USART0_RX_BUF[USART0_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
uint16_t USART0_RX_STA=0; //接收状态标记
void uart0_init(uint32_t bound)
{
//初始化
gd_eval_com_init(EVAL_COM);
//设置波特率
usart_baudrate_set(EVAL_COM, bound);
#if EN_USART0_TX
//使能发送中断
usart_interrupt_enable(USART0, USART_INT_TBE);
#endif
#if EN_USART0_RX //如果使能了接收
//使能接收中断
usart_interrupt_enable(USART0, USART_INT_RBNE);
/* USART interrupt configuration */
nvic_irq_enable(USART0_IRQn, 0);
#endif
}
void USART0_IRQHandler(void) //串口1中断服务程序
{
#if EN_USART0_RX
uint8_t Res;
if(usart_interrupt_flag_get(EVAL_COM, USART_INT_FLAG_RBNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =usart_data_receive(EVAL_COM); //读取接收到的数据
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;//接收数据错误,重新开始接收
}
}
}
}
#endif
#if EN_USART0_TX
if(usart_interrupt_flag_get(EVAL_COM, USART_INT_FLAG_TBE)!= RESET)
{
/* transmit data */
// usart_data_transmit(EVAL_COM, transmitter_buffer[txcount++]);
// if(txcount == transfersize){
// usart_interrupt_disable(EVAL_COM, USART_INT_TBE);
// }
}
#endif
}
/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
usart_data_transmit(USART0, (uint8_t) ch);
while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
return ch;
}
main函数中,做如下修改:
/*!
\file main.c
\brief running LED
\version 2019-02-19, V1.0.0, firmware for GD32E23x
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32e23x.h"
#include "gd32e230c_eval.h"
#include "systick.h"
#include <stdio.h>
#include "usart0.h"
/*!
\brief main function
\param[in] none
\param[out] none
\retval none
*/
int main(void)
{
uint16_t t;
uint16_t len;
uint16_t times=0;
//时钟初始化
systick_config();
//初始化LED
gd_eval_led_init(LED1);
gd_eval_led_init(LED2);
gd_eval_led_init(LED3);
gd_eval_led_init(LED4);
gd_eval_led_off(LED1);
gd_eval_led_off(LED2);
gd_eval_led_off(LED3);
gd_eval_led_off(LED4);
//初始化按键
gd_eval_key_init(KEY_WAKEUP,KEY_MODE_GPIO);
//初始化串口0
uart0_init(115200);
// while(gd_eval_key_state_get(KEY_WAKEUP)==SET)
// {
// printf("please press wakeup_key to continue!\r\n");
// delay_1ms(200);
// }
while(1){
// /* turn on LED1, turn off LED4 */
// gd_eval_led_on(LED1);
// gd_eval_led_off(LED4);
// delay_1ms(1000);
// /* turn on LED2, turn off LED1 */
// gd_eval_led_on(LED2);
// gd_eval_led_off(LED1);
// delay_1ms(1000);
// /* turn on LED3, turn off LED2 */
// gd_eval_led_on(LED3);
// gd_eval_led_off(LED2);
// delay_1ms(1000);
// /* turn on LED4, turn off LED3 */
// gd_eval_led_on(LED4);
// gd_eval_led_off(LED3);
// delay_1ms(1000);
if(USART0_RX_STA&0x8000)
{
len=USART0_RX_STA&0x3fff;//得到此次接收到的数据长度
printf("\r\n您发送的消息为:\r\n\r\n");
for(t=0;t<len;t++)
{
usart_data_transmit(USART0,(uint8_t) USART0_RX_BUF[t]);//向串口1发送数据
while(usart_flag_get(USART0, USART_FLAG_TBE)!=SET);//等待发送结束
}
printf("\r\n\r\n");//插入换行
USART0_RX_STA=0;
}else
{
times++;
if(times%5000==0)
{
printf("\r\nGD32E230C8T6 串口实验\r\n");
printf("----20210730----\r\n\r\n");
}
if(times%200==0)printf("请输入数据,以回车键结束\n");
if(times%30==0)gd_eval_led_toggle(LED1);//闪烁LED,提示系统正在运行.
delay_1ms(10);
}
}
}
串口PRINTF重定义,别忘了勾选:
下载,编译,查看串口,并输入字符:
下面我们测试当前的ADC,我们选择PA2作为ADC的CH2,使用DMA,使用TIMER0作为外部触发(其内部与ADC触发引脚已相连)
我们写ADC初始化代码,我们设置ADC时钟为12M,采样点位220个,采样频率为TIMER0的PWM频率120K:
void adc_init(void)
{
//////////////时钟初始化/////////////////
/* enable the GPIO clock */
//使能对应GPIO PIN时钟
rcu_periph_clock_enable(RCU_GPIOA);
/* ADCCLK = PCLK2/6 */
//ADC时钟分频
rcu_adc_clock_config(RCU_ADCCK_APB2_DIV6);
/* enable DMA clock */
//使能DMA时钟
rcu_periph_clock_enable(RCU_DMA);
/* enable ADC clock */
//使能ADC时钟
rcu_periph_clock_enable(RCU_ADC);
/* enable TIMER0 clock */
//使能TIMER0时钟
rcu_periph_clock_enable(RCU_TIMER0);
/////////////配置输入引脚//////////////////////
/* configure PA2(ADC channel2) as analog input */
//配置PA2为模拟输入
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_2);
//////////////配置DMA/////////////////////////
dma_parameter_struct dma_init_struct;
/* initialize DMA channel0 */
dma_deinit(DMA_CH0);
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_init_struct.memory_addr = (uint32_t)ad_value;
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;
dma_init_struct.number = sample_num;
dma_init_struct.periph_addr = (uint32_t)&(ADC_RDATA);
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_init(DMA_CH0, &dma_init_struct);
/* configure DMA mode */
dma_circulation_enable(DMA_CH0);
dma_memory_to_memory_disable(DMA_CH0);
/* enable DMA channel0 */
dma_channel_enable(DMA_CH0);
//////////////配置采样时钟TIMER0/////////////
timer_oc_parameter_struct timer_ocintpara;
timer_parameter_struct timer_initpara;
timer_deinit(TIMER0);
/* TIMER0 configuration */
timer_initpara.prescaler = 5;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 399;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER0, &timer_initpara);
/* CH0 configuration in PWM mode1 */
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_LOW;
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_channel_output_config(TIMER0, TIMER_CH_0, &timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, 100);
timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM1);
timer_channel_output_shadow_config(TIMER0, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE);
/* auto-reload preload enable */
timer_auto_reload_shadow_enable(TIMER0);
timer_primary_output_config(TIMER0, ENABLE);
/////////////////ADC配置///////////////////////////
/* ADC channel length config */
adc_channel_length_config(ADC_REGULAR_CHANNEL, 1);
/* ADC regular channel config */
adc_regular_channel_config(0, ADC_CHANNEL_2, ADC_SAMPLETIME_55POINT5);
/* ADC external trigger enable */
adc_external_trigger_config(ADC_REGULAR_CHANNEL, ENABLE);
/* ADC external trigger source config */
adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_T0_CH0);
/* ADC data alignment config */
adc_data_alignment_config(ADC_DATAALIGN_RIGHT);
/* enable ADC interface */
adc_enable();
/* ADC calibration and reset calibration */
adc_calibration_enable();
/* ADC DMA function enable */
adc_dma_mode_enable();
}
采样开启和关闭,通过开关TIMER0,累加220,然后求平均值,并串口输出:
#include "usart0.h"
void ADC_getvalue_Tast(void)
{
uint16_t i=0;
uint32_t ADC_VALUE=0;
float voltage_value=0.0;
/* TIMER0 counter enable */
//开启采样
timer_enable(TIMER0);
/* test on channel0 transfer complete flag */
//等待设定的220个采样点结束
while( !dma_flag_get(DMA_CH0, DMA_FLAG_FTF));
/* clear channel0 transfer complete flag */
dma_flag_clear(DMA_CH0, DMA_FLAG_FTF);
/* TIMER0 counter disable */
//关闭采样
timer_disable(TIMER0);
//串输出采样数值
for(i=0;i<sample_num;i++)
{
ADC_VALUE=ad_value[i]*3300/4096+ADC_VALUE;//转换成mv
}
voltage_value=ADC_VALUE/sample_num*1.00;
printf("the ADC_CH2 VOLTAGE IS : %.2f mv\r\n",voltage_value);
}
具体代码:
ADC.H
#ifndef __ADC_H_
#define __ADC_H_
#include "stdio.h"
#include "gd32e23x.h"
#include "gd32e230c_eval.h"
#include "systick.h"
#define sample_num 220 //定义采样点
extern uint16_t ad_value[sample_num];
void adc_init(void);
void ADC_getvalue_Tast(void);
#endif
ADC.C
#include "adc.h"
uint16_t ad_value[sample_num];
//PA2 ADC_CH2
void adc_init(void)
{
//////////////时钟初始化/////////////////
/* enable the GPIO clock */
//使能对应GPIO PIN时钟
rcu_periph_clock_enable(RCU_GPIOA);
/* ADCCLK = PCLK2/6 */
//ADC时钟分频
rcu_adc_clock_config(RCU_ADCCK_APB2_DIV6);
/* enable DMA clock */
//使能DMA时钟
rcu_periph_clock_enable(RCU_DMA);
/* enable ADC clock */
//使能ADC时钟
rcu_periph_clock_enable(RCU_ADC);
/* enable TIMER0 clock */
//使能TIMER0时钟
rcu_periph_clock_enable(RCU_TIMER0);
/////////////配置输入引脚//////////////////////
/* configure PA2(ADC channel2) as analog input */
//配置PA2为模拟输入
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_2);
//////////////配置DMA/////////////////////////
dma_parameter_struct dma_init_struct;
/* initialize DMA channel0 */
dma_deinit(DMA_CH0);
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_init_struct.memory_addr = (uint32_t)ad_value;
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;
dma_init_struct.number = sample_num;
dma_init_struct.periph_addr = (uint32_t)&(ADC_RDATA);
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_init(DMA_CH0, &dma_init_struct);
/* configure DMA mode */
dma_circulation_enable(DMA_CH0);
dma_memory_to_memory_disable(DMA_CH0);
/* enable DMA channel0 */
dma_channel_enable(DMA_CH0);
//////////////配置采样时钟TIMER0/////////////
timer_oc_parameter_struct timer_ocintpara;
timer_parameter_struct timer_initpara;
timer_deinit(TIMER0);
/* TIMER0 configuration */
timer_initpara.prescaler = 5;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 399;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER0, &timer_initpara);
/* CH0 configuration in PWM mode1 */
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_LOW;
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_channel_output_config(TIMER0, TIMER_CH_0, &timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, 100);
timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM1);
timer_channel_output_shadow_config(TIMER0, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE);
/* auto-reload preload enable */
timer_auto_reload_shadow_enable(TIMER0);
timer_primary_output_config(TIMER0, ENABLE);
/////////////////ADC配置///////////////////////////
/* ADC channel length config */
adc_channel_length_config(ADC_REGULAR_CHANNEL, 1);
/* ADC regular channel config */
adc_regular_channel_config(0, ADC_CHANNEL_2, ADC_SAMPLETIME_55POINT5);
/* ADC external trigger enable */
adc_external_trigger_config(ADC_REGULAR_CHANNEL, ENABLE);
/* ADC external trigger source config */
adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_T0_CH0);
/* ADC data alignment config */
adc_data_alignment_config(ADC_DATAALIGN_RIGHT);
/* enable ADC interface */
adc_enable();
/* ADC calibration and reset calibration */
adc_calibration_enable();
/* ADC DMA function enable */
adc_dma_mode_enable();
}
#include "usart0.h"
void ADC_getvalue_Tast(void)
{
uint16_t i=0;
uint32_t ADC_VALUE=0;
float voltage_value=0.0;
/* TIMER0 counter enable */
//开启采样
timer_enable(TIMER0);
/* test on channel0 transfer complete flag */
//等待设定的220个采样点结束
while( !dma_flag_get(DMA_CH0, DMA_FLAG_FTF));
/* clear channel0 transfer complete flag */
dma_flag_clear(DMA_CH0, DMA_FLAG_FTF);
/* TIMER0 counter disable */
//关闭采样
timer_disable(TIMER0);
//串输出采样数值
for(i=0;i<sample_num;i++)
{
ADC_VALUE=ad_value[i]*3300/4096+ADC_VALUE;//转换成mv
}
voltage_value=ADC_VALUE/sample_num*1.00;
printf("the ADC_CH2 VOLTAGE IS : %.2f mv\r\n",voltage_value);
}
main函数里面调用:
//初始化ADC
adc_init();
.......
while(1)
{
ADC_getvalue_Tast();
delay_1ms(1000);
}
调试下载。并分别测试0V和3.3V
好了,基本的测试先到这~
总体而言没发现啥特别,上手也不难,库写的可读写也可以。
总而言之,国产MCU与国外的差距越来越小了~
|
此文章已获得独家原创/原创奖标签,著作权归21ic所有,未经允许禁止转载。
打赏榜单
21小跑堂 打赏了 50.00 元 2021-07-30 理由:恭喜通过原创文章审核!请多多加油哦!
共1人点赞
|