GD32F30x系列ADC源码
- 【1】adc_reg.h [参考]
- 【2】ctrl_adc.h [重点]
- 【3】gd32f30x_dma_reg.h [参考]
- 【4】mon_adc.h [参考 +1]
- 【5】rcu.h [参考]
- 【6】ctrl_adc.c [重要]
- 【7】mon_adc.c [参考+1]
- 【8】main.c [参考+2]
这篇文章必须配合这个连接文件一起看,即ADC手册
嵌入式通用const和volatile和static inline关键字 (记得不懂const和volatile可以看这篇)
学习完ADC寄存器后,其他寄存器都是模仿式学习,做嵌入式重在坚持,贵在坚持
【1】adc_reg.h [参考]
#ifndef CTRL_ADC_H
#define CTRL_ADC_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdio.h>
#define __IO volatile //值可以被改变 每次必须从内存获取值 防止被编译器优化
#define __I volatile const //值不希望被改变,保持这个值为只读常量
#define __STATIC_INLINE static inline //内敛函数 适用代码短的函数
#if defined(__CC_ARM)
#pragma anon_unions //keil中默认是不支持匿名结构体的,需要编译指令#pragma anon_unions指名。
#elif defined(CCARM__)
#pragma language=extended //IAR对所用语言(这里是C)做的一些扩展,也就是说这里可以用扩展的功能
#elif defined (__ICCARM__)
/* anonymous unions are enabled by default:默认启用匿名联合 */
#elif defined(__GNUC__)
/* anonymous unions are enabled by default */
#elif defined(__TMS470__)
/* anonymous unions are enabled by default */
#elif defined(__TASKING__)
#pragma warning 586
#else
#warning Not supported compiler type //警告不支持编译器类型
#endif
/*============================控制MCU部分==========================*/
/* 通道号 */
#define ADC_CHANNEL_0 0x00
#define ADC_CHANNEL_1 0x01
#define ADC_CHANNEL_2 0x02
#define ADC_CHANNEL_3 0x03
#define ADC_CHANNEL_4 0x04
#define ADC_CHANNEL_5 0x05
#define ADC_CHANNEL_6 0x06
#define ADC_CHANNEL_7 0x07
#define ADC_CHANNEL_8 0x08
#define ADC_CHANNEL_9 0x09
#define ADC_CHANNEL_10 0x0A
#define ADC_CHANNEL_11 0x0B
#define ADC_CHANNEL_12 0x0C
#define ADC_CHANNEL_13 0x0D
#define ADC_CHANNEL_14 0x0E
#define ADC_CHANNEL_15 0x0F
#define ADC_CHANNEL_16 0x10
#define ADC_CHANNEL_17 0x11
/* 规则组长度 ADC_RSQ0.Bits.RL */
#define REGULAR_LEN_1 0x00
#define REGULAR_LEN_2 0x01
#define REGULAR_LEN_3 0x02
#define REGULAR_LEN_4 0x03
#define REGULAR_LEN_5 0x04
#define REGULAR_LEN_6 0x05
#define REGULAR_LEN_7 0x06
#define REGULAR_LEN_8 0x07
#define REGULAR_LEN_9 0x08
#define REGULAR_LEN_10 0x09
#define REGULAR_LEN_11 0x0A
#define REGULAR_LEN_12 0x0B
#define REGULAR_LEN_13 0x0C
#define REGULAR_LEN_14 0x0D
#define REGULAR_LEN_15 0x0E
#define REGULAR_LEN_16 0x0F
/*注入组长度 注入通道,x=0,1,2,3 数据偏移值,取值范围为0~4095*/
#define INSERTED_LEN_1 0x00
#define INSERTED_LEN_2 0x01
#define INSERTED_LEN_3 0x02
#define INSERTED_len_4 0x03
/*ADC的采样时间*/
#define ADC_SAMPLETIME_1POINT5 //1.5 周期
#define ADC_SAMPLETIME_7POINT5 //7.5 周期
#define ADC_SAMPLETIME_13POINT5 //13.5 周期
#define ADC_SAMPLETIME_28POINT5 //28.5 周期
#define ADC_SAMPLETIME_41POINT5 //41.5 周期
#define ADC_SAMPLETIME_55POINT5 //55.5 周期
#define ADC_SAMPLETIME_71POINT5 //71.5 周期
#define ADC_SAMPLETIME_239POINT5 //239.5 周期
/*ADC 分辨率*/
#define ADC_RESOLUTION_12B //12位
#define ADC_RESOLUTION_10B //10位
#define ADC_RESOLUTION_8B //8位
#define ADC_RESOLUTION_6B //6位
/*ADC 通道组*/ //间断模式下的转换数目,规则通道组取值为1..8,注入通道组取值无意义
//ADC通道选择ADC_CHANNEL_x(x=0..17) ADC 通道x (x=0..17)(只有ADC0,可取值x=16和17 )
#define ADC_REGULAR_CHANNEL //规则通道组
#define ADC_INSERTED_CHANNEL//注入通道组
/*ADC 运行模式*/
#define ADC_MODE_FREE //所有ADC运行于独立模式
#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL //ADC0和ADC1运行在规则并行+注入并行组合模式
#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION //ADC0和ADC1运行在规则并行+交替触发组合模式
#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST //ADC0和ADC1运行在注入并行+快速交叉组合模式
#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW //ADC0和ADC1运行在注入并行+慢速交叉组合模式
#define ADC_DAUL_INSERTED_PARALLEL //ADC0和ADC1运行在注入并行模式
#define ADC_DAUL_REGULAL_PARALLEL //ADC0和ADC1运行在规则并行模式
#define ADC_DAUL_REGULAL_FOLLOWUP_FAST //ADC0和ADC1运行在快速交叉模式
#define ADC_DAUL_REGULAL_FOLLOWUP_SLOW //ADC0和ADC1运行在慢速交叉模式
#define ADC_DAUL_INSERTED_TRRIGGER_ROTATION //ADC0和ADC1运行在交替触发模式
/*ADC 功能配置*/
#define ADC_SCAN_MODE //扫描模式选择
#define ADC_INSERTED_CHANNEL_AUTO //注入组自动转换
#define ADC_CONTINUOUS_MODE //连续模式选择
/*ADC 规则通道组或注入通道组触发源*/
#define ADC0_1_EXTTRIG_REGULAR_T0_CH0 //TIMER0 CH0事件(规则组)
#define ADC0_1_EXTTRIG_REGULAR_T0_CH1 //TIMER0 CH1事件(规则组)
#define ADC0_1_EXTTRIG_REGULAR_T0_CH2 //TIMER0 CH2事件(规则组)
#define ADC0_1_EXTTRIG_REGULAR_T1_CH1 //TIMER1 CH1事件(规则组)
#define ADC0_1_EXTTRIG_REGULAR_T2_TRGO //TIMER2TRGO事件(规则组)
#define ADC0_1_EXTTRIG_REGULAR_T3_CH3 //TIMER3 CH3事件(规则组)
#define ADC0_1_EXTTRIG_REGULAR_T7_TRGO //TIMER7 TRGO事件(规则组)
#define ADC0_1_EXTTRIG_REGULAR_EXTI_11 //外部中断线11(规则组)
#define ADC2_EXTTRIG_REGULAR_T2_CH0 //TIMER2 CH0事件(规则组)
#define ADC2_EXTTRIG_REGULAR_T1_CH2 //TIMER1 CH2事件(规则组)
#define ADC2_EXTTRIG_REGULAR_T0_CH2 //TIMER0 CH2事件(规则组)
#define ADC2_EXTTRIG_REGULAR_T7_CH0 //TIMER7CH0事件(规则组)
#define ADC2_EXTTRIG_REGULAR_T7_TRGO //TIMER7 TRGO事件(规则组)
#define ADC2_EXTTRIG_REGULAR_T4_CH0 //TIMER4 CH0事件(规则组)
#define ADC2_EXTTRIG_REGULAR_T4_CH2 //TIMER4 CH2事件(规则组)
#define ADC0_1_2_EXTTRIG_REGULAR_NONE //软件触发(规则组)
#define ADC0_1_EXTTRIG_INSERTED_T0_TRGO //TIMER0 TRGO事件(注入组)
#define ADC0_1_EXTTRIG_INSERTED_T0_CH3 //TIMER0 CH3事件(注入组)
#define ADC0_1_EXTTRIG_INSERTED_T1_TRGO //TIMER1 TRGO事件(注入组)
#define ADC0_1_EXTTRIG_INSERTED_T1_CH0 //TIMER1 CH0事件(注入组)
#define ADC0_1_EXTTRIG_INSERTED_T2_CH3 //TIMER2 CH3事件(注入组)
#define ADC0_1_EXTTRIG_INSERTED_T3_TRGO //TIMER3 TRGO事件(注入组)
#define ADC0_1_EXTTRIG_INSERTED_EXTI_15 //外部中断线15 (注入组)
#define ADC0_1_EXTTRIG_INSERTED_T7_CH3 //TIMER7 CH3事件(注入组)
#define ADC2_EXTTRIG_INSERTED_T0_TRGO //TIMER0 TRGO事件(注入组)
#define ADC2_EXTTRIG_INSERTED_T0_CH3 //TIMER0 CH3事件(注入组)
#define ADC2_EXTTRIG_INSERTED_T3_CH2 //TIMER3 CH2事件(注入组)
#define ADC2_EXTTRIG_INSERTED_T7_CH1 //TIMER7 CH1事件(注入组)
#define ADC2_EXTTRIG_INSERTED_T7_CH3 //TIMER7 CH3事件(注入组)
#define ADC2_EXTTRIG_INSERTED_T4_TRGO //TIMER4 TRGO事件(注入组)
#define ADC2_EXTTRIG_INSERTED_T4_CH3 //TIMER4 CH3事件(注入组)
#define ADC0_1_2_EXTTRIG_INSERTED_NONE //软件触发(注入组)
/*ADC标志位*/
#define ADC_FLAG_WDE //模拟看门狗事件标志位
#define ADC_FLAG_EOC //转换结束标志位
#define ADC_FLAG_EOIC //注入通道组转换结束标志位
#define ADC_FLAG_STIC //注入通道组转换开始标志位
#define ADC_FLAG_STRC //规则通道组转换开始标志位
/*ADC过采样触发模式*/
#define ADC_OVERSAMPLING_ALL_CONVERT //在一个触发之后,对一个通道连续进行过采样转换
#define ADC_OVERSAMPLING_ONE_CONVERT //在一个触发之后,对一个通道只进行一次过采样转换
typedef struct {
union{
struct//ADC标志位 从低位->高位
{ //WDE-》转换电压超过ADC_WDLT和ADC_WDHT寄存器设定的阈值时由硬件置1,软件写0清除。
__IO uint32_t WDE :1; //模拟看门狗事件 1:产生模拟看门狗事件 0:没有模拟看门狗事件
__IO uint32_t EOC :1; //组转换结束 1:转化结束 0:未结束转化 转化结束时硬件会置1 软件写0清除或读ADC_RDATA寄存器清除
__IO uint32_t EOIC :1; //注入通道组转换结束 1:转化结束 0:未结束转化 转化结束时硬件会置1 软件写0清除
__IO uint32_t STIC :1; //注入通道组转换开始 1:开始转化 0:未开启转化 转化开始时硬件会置1 软件写0清除
__IO uint32_t STRC :1; //规则通道组转换开始 1:开始转化 0:未开启转化 转化开始时硬件会置1 软件写0清除
__IO uint32_t :27; //保留 必须保留复位值
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 C000 -》0000 0000 0000 0000 1100 0000 0000 0000 (32位)
}ADC_STAT; // 地址偏移: 0x00 状态寄存器
union{
struct
{
__IO uint32_t WDCHSEL :5; //模拟看门狗通道选择
/*
* 00000: ADC 通道 0
00001: ADC 通道 1
00010: ADC 通道 2
00011: ADC 通道 3
00100: ADC 通道 4
00101: ADC 通道 5
00110: ADC 通道 6
00111: ADC 通道 7
01000: ADC 通道 8
01001: ADC 通道 9
01010: ADC 通道 10
01011: ADC 通道 11
01100: ADC 通道 12
01101: ADC 通道 13
01110: ADC 通道 14
01111: ADC 通道 15
10000: ADC 通道 16
10001: ADC 通道 17
其他值保留
注意: ADC0 的模拟输入通道 16 和通道 17 分别连接到温度传感器和 VREFINT。
ADC1 的模拟输入通道 16 和通道 17 内部都连接到 VSSA。 ADC2 的模拟输入通道
16 和通道 17 内部都连接到 VSSA。
*/
__IO uint32_t EOCIE :1; //EOC中断使能 0:EOC 中断禁止 1:EOC 中断使能
__IO uint32_t WDEIE :1; //模拟看门狗事件 中断使能 0:WDE 中断禁止 1:WDE 中断使能
__IO uint32_t EOICIE :1; //EOIC 中断使能 0:禁止 1:使能
__IO uint32_t SM :1; //扫描转换模式 0:禁止 1:使能
__IO uint32_t WDSC :1; //扫描模式下,模拟看门狗在单通道有效 0:模拟看门狗在所有通道有效 1:模拟看门狗在单通道有效
__IO uint32_t ICA :1; //注入组自动转换 0:禁止 1:使能
__IO uint32_t DISRC :1; //规则组间断模式 0:禁止 1:使能
__IO uint32_t DISIC :1; //注入组间断模式 0:禁止 1:使能
__IO uint32_t DISNUM :3; //间断模式下的转换数目 触发后即将被转换的通道数目将变成 DISNUM[2:0]+1
__IO uint32_t SYNCM :4; //ADC 同步模式选择 0000:独立模式
/*
0000:独立模式
0001:规则并行+注入并行组合模式
0010:规则并行+交替触发组合模式
0011:注入并行+快速交叉组合模式
0100:注入并行+慢速交叉组合模式
0101:注入并行模式
0110:规则并行模式
0111:快速交叉模式
1000:慢速交叉模式
1001:交替触发模式
注意:在 ADC1 和 ADC2 中这些位为保留位。在同步模式下,改变通道的配置会产
生一个重新开始的条件,会导致同步丢失,建议在任何配置之前关闭同步模式。
*/
__IO uint32_t :2;
__IO uint32_t IWDEN :1;//注入组看门狗使能 0:禁止 1:使能
__IO uint32_t RWDEN :1;//规则组看门狗使能 0:禁止 1:使能
__IO uint32_t :8;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_CTL0; // 地址偏移: 0x04 控制寄存器 0
union{
struct
{
__IO uint32_t ADCON :1; //ADC 上电使能位 0:禁止 ADC 关闭电源 1:使能 ADC
/*开启 ADC。该位从‘0’变成‘1’将在稳定时间结束后唤醒 ADC。当该位被置位以后,不
改变寄存器的其他位仅仅对该位写‘1’, 将开启转换。*/
__IO uint32_t CTN :1; //0:禁止连续模式,1:使能连续模式
__IO uint32_t CLB :1; /* ADC 校准 : 0:校准结束 1:校准开始 */
__IO uint32_t RSTCLB :1; /* 校准复位: 软件置位(1), 在校准寄存器初始化后该位硬件清零 0:校准结束 1:校准开始*/
__IO uint32_t :4; //7:4 保留 必须保持复位值。
__IO uint32_t DMA :1; //DMA 请求使能 0:禁止 1:使能
__IO uint32_t :2; //10:9 保留 必须保持复位值。
__IO uint32_t DAL :1; //数据对齐 0:最低有效位对齐 1:最高有效位对齐
__IO uint32_t ETSIC :3; //注入组外部触发选择
/*14:12 ETSIC[2:0]
对于 ADC0 与 ADC1:
000:定时器 0 TRGO
001:定时器 0 CH3
010:定时器 1 TRGO
011:定时器 1 CH0
100:定时器 2 CH3
101:定时器 3 TRGO
110:中断线 15/定时器 7 CH3
111:软件触发
对于 ADC2:
000:定时器 0 TRGO
001:定时器 0 CH3
010:定时器 3 CH2
011:定时器 7 CH1
100:定时器 7 CH3
101:定时器 4 TRGO
110:定时器 4 CH3
111:软件触发
*/
__IO uint32_t ETEIC :1; //注入组外部触发使能 0:禁止 1:使能
__IO uint32_t :1; //必须保持复位值。
__IO uint32_t ETSRC :3; //规则组外部触发选择: 111:软件触发
/*19:17 ETSRC[2:0]
对于 ADC0 与 ADC1:
000:定时器 0 CH0
001:定时器 0 CH1
010:定时器 0 CH2
011:定时器 1 CH1
100:定时器 2 TRGO
101:定时器 3 CH3
110:中断线 11/定时器 7 TRGO
111:软件触发
对于 ADC2:
000:定时器 2 CH0
001:定时器 1 CH2
010:定时器 0 CH2
011:定时器 7 CH0
100:定时器 7 TRGO
101:定时器 4 CH0
110:定时器 4 CH2
111:软件触发
*/
__IO uint32_t ETERC :1; //规则组外部触发使能 0:禁止 1:使能
__IO uint32_t SWICST :1; //注入组转换开始: 如果 ETSRC 是 111,该位置‘1’开启规则组转换。软件置位,软件清零,或转换开始后,由硬件清零
__IO uint32_t SWRCST :1; //规则组转换开始: 如果 ETSIC 是 111,该位置‘1’开启注入组转换。软件置位,软件清零,或转换开始后,由硬件清零
__IO uint32_t TSVREN :1; // 将ADC_CTL1 寄存器的 TSVREN 位置 1可以使能温度传感器通道(ADC0_CH16)和 VREFINT通道(ADC0_CH17)。
__IO uint32_t :8; //保留 必须保持复位值
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_CTL1; // 地址偏移: 0x08 控制寄存器 1
union{
struct
{
__IO uint32_t SPT10 :3;//通道采样时间
/*
000:1.5 周期
001:7.5 周期
010:13.5 周期
011:28.5 周期
100:41.5 周期
101:55.5 周期
110:71.5 周期
111:239.5 周期
*/
__IO uint32_t SPT11 :3;//参考 SPT10[2:0]的描述
__IO uint32_t SPT12 :3;//参考 SPT10[2:0]的描述
__IO uint32_t SPT13 :3;//参考 SPT10[2:0]的描述
__IO uint32_t SPT14 :3;//参考 SPT10[2:0]的描述
__IO uint32_t SPT15 :3;//参考 SPT10[2:0]的描述
__IO uint32_t SPT16 :3;//参考 SPT10[2:0]的描述
__IO uint32_t SPT17 :3;//参考 SPT10[2:0]的描述
__IO uint32_t :8;//31:24 保留 必须保持复位值。
}Bits; 0000 0000 1111 1111 1111 1111 11111 1111
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_SAMPT0; // 地址偏移: 0x0C 采样时间寄存器 0
union{
struct
{
__IO uint32_t SPT0 :3;//通道采样时间
/*
000:1.5 周期
001:7.5 周期
010:13.5 周期
011:28.5 周期
100:41.5 周期
101:55.5 周期
110:71.5 周期
111:239.5 周期
*/
__IO uint32_t SPT1 :3;//参考 SPT0[2:0]的描述
__IO uint32_t SPT2 :3;//参考 SPT0[2:0]的描述
__IO uint32_t SPT3 :3;//参考 SPT0[2:0]的描述
__IO uint32_t SPT4 :3;//参考 SPT0[2:0]的描述
__IO uint32_t SPT5 :3;//参考 SPT0[2:0]的描述
__IO uint32_t SPT6 :3;//参考 SPT0[2:0]的描述
__IO uint32_t SPT7 :3;//参考 SPT0[2:0]的描述
__IO uint32_t SPT8 :3;//参考 SPT0[2:0]的描述
__IO uint32_t SPT9 :3;//参考 SPT0[2:0]的描述
__IO uint32_t :2;//31:30 保留 必须保持复位值。
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_SAMPT1; // 地址偏移: 0x10 采样时间寄存器 1
union{
struct
{
__IO uint32_t IOFF :12;//注入通道 x 的数据偏移
/*当转换注入通道时,这些位定义了用于从原始转换数据中减去的数值。转换的结果
可以在 ADC_IDATAx 寄存器中读出。*/
__IO uint32_t :20;//31:12 保留 必须保持复位值。
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_IOFF0; // 地址偏移: 0x14 注入通道数据偏移寄存器 0
union{
struct
{
__IO uint32_t IOFF :12;
__IO uint32_t :20;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_IOFF1; // 地址偏移: 0x18 注入通道数据偏移寄存器 1
union{
struct
{
__IO uint32_t IOFF :12;
__IO uint32_t :20;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_IOFF2; // 地址偏移: 0x1C 注入通道数据偏移寄存器 2
union{
struct
{
__IO uint32_t IOFF :12;
__IO uint32_t :20;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_IOFF3; // 地址偏移: 0x20 注入通道数据偏移寄存器 3
union{
struct
{
__IO uint32_t WDHT :12;//模拟看门狗高阈值
__IO uint32_t :20;//31:12 保留 必须保持复位值。
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_WDHT; // 地址偏移: 0x24 看门狗高阈值寄存器 模拟看门狗高阈值,0..4095
union{
struct
{
__IO uint32_t WDLT :12;//模拟看门狗低阈值 这些位定义了模拟看门狗的低阈值。
__IO uint32_t :20;//31:12 保留 必须保持复位值。
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_WDLT; // 地址偏移: 0x28 看门狗低阈值寄存器 模拟看门狗低阈值,0..4095
union{
struct
{
__IO uint32_t RSQ12 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ13 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ14 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ15 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RL :4;//规则组长度,0-F表示1-16个 规则通道转换序列中的总的通道数目为 RL[3:0]+1。
__IO uint32_t :8;//31:24 保留 必须保持复位值。
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_RSQ0; // 地址偏移: 0x2C 规则序列寄存器 0
union{
struct
{
__IO uint32_t RSQ6 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ7 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ8 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ9 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ10 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ11 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t :2;//31:30 保留 必须保持复位值。
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_RSQ1; // 地址偏移: 0x30 规则序列寄存器 1
union{
struct
{
__IO uint32_t RSQ0 :5;//通道编号(0..17)写入这些位来选择规则通道的第 n 个转换的通道
__IO uint32_t RSQ1 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ2 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ3 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ4 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ5 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t :2;//31:30 保留 必须保持复位值。
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_RSQ2; // 地址偏移: 0x34 规则序列寄存器 2
union{
struct
{
__IO uint32_t ISQ0 :5;//通道编号(0..17)写入这些位来选择注入组的第 n 个转换的通道
/*
和规则通道转换序列不同的是,如果 IL[1:0]长度不足 4,注入通道转换从(4-IL[1:0]-
1) 开始。
IL 注入通道转换顺序
3 ISQ0 >> ISQ1 >> ISQ2 >> ISQ3
2 ISQ1 >> ISQ2 >> ISQ3
1 ISQ2 >> ISQ3
0 ISQ3
*/
__IO uint32_t ISQ1 :5;//参考 ISQ0[4:0]的描述
__IO uint32_t ISQ2 :5;//参考 ISQ0[4:0]的描述
__IO uint32_t ISQ3 :5;//参考 ISQ0[4:0]的描述
__IO uint32_t IL :2;//注入序列长度 注入组总的通道数目为 IL[1:0]+1。
__IO uint32_t :10;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_ISQ; // 地址偏移: 0x38 注入序列寄存器
union{
struct
{
__I uint32_t IDATAn :16;//注入转换的数据 n 这些位包含了注入通道的转换结果,只读。
__I uint32_t :16;
}Bits;
__I uint32_t Byte; // 复位值: 0x0000 0000
}ADC_IDATA0; // 地址偏移: 0x3C 注入数据寄存器 0
union{
struct
{
__I uint32_t IDATAn :16;//注入转换的数据 n 这些位包含了注入通道的转换结果,只读。
__I uint32_t :16;
}Bits;
__I uint32_t Byte; // 复位值: 0x0000 0000
}ADC_IDATA1; // 地址偏移: 0x40 注入数据寄存器 1
union{
struct
{
__I uint32_t IDATAn :16;//注入转换的数据 n 这些位包含了注入通道的转换结果,只读。
__I uint32_t :16;
}Bits;
__I uint32_t Byte; // 复位值: 0x0000 0000
}ADC_IDATA2; // 地址偏移: 0x44 注入数据寄存器 2
union{
struct
{
__I uint32_t IDATAn :16;//注入转换的数据 n 这些位包含了注入通道的转换结果,只读。
__I uint32_t :16;
}Bits;
__I uint32_t Byte; // 复位值: 0x0000 0000
}ADC_IDATA3; // 地址偏移: 0x48 注入数据寄存器 3
union{
struct
{
__I uint32_t RDATA :16; //规则通道数据 这些位包含了规则通道的转换结果,只读。
/*ADC0:在同步模式下,这些位包含着 ADC1 的规则通道数据
ADC1 和 ADC2:这些位没有使用.*/
__I uint32_t ADC1RDTR :16; //规则通道数据 ADC1
}Bits;
__I uint32_t Byte; // 复位值: 0x0000 0000
}ADC_RDATA; // 地址偏移: 0x4C 规则数据寄存器
/*============================================================================*/
//注意:当 ADCON= 0 时软件才允许写该位(确定没有转换正在进行) 本次项目禁用这项
union{
struct{
__IO uint32_t OVSEN :1; //过滤采样使能 0:过滤采样失能 1:过滤采样使能 注意:当 ADCON=0 时软件才允许写该位(确定没有转换正在进行)
__IO uint32_t :1; //1 保留 必须保持复位值。
__IO uint32_t OVSR :3; //过采样率
/*
这些位定义了过采样率的大小.
000:2x
001:4x
010:8x
011:16x
100:32x
101:64x
110:128x
111:256x
注意:当 ADCON=0 时软件才允许写该位(确定没有转换正在进行)
*/
__IO uint32_t OVSS :4; //过滤采样移位
/*
该位通过软件设置和清除.
0000:不移位
0001:移 1 位
0010:移 2 位
0011:移 3 位
0100:移 4 位
0101:移 5 位
0110:移 6 位
0111:移 7 位
1000:移 8 位
其他保留
注意:当 ADCON=0 时软件才允许写该位(确定没有转换正在进行).
*/
__IO uint32_t TOVS :1; //触发过滤采样
/*该位通过软件设置和清除.
0:所有的过滤采样连续转换完成一个触发后
1:对于过采样通道的每次转换都需要一次触发,触发次数由过采样率
(OVSR[2:0])决定。
注意:当 ADCON= 0 时软件才允许写该位(确定没有转换正在进行).*/
__IO uint32_t :2;
__IO uint32_t DRES :2; //ADC 分辨率
/*13:12 DRES[1:0] ADC 分辨率
ADC 分辨率
00:12 位
01:10 位
10:8 位
11:6 位
*/
__IO uint32_t :18;
}Bits;
__I uint32_t Byte;
}ADC_OVSAMPCTL;//过采样控制寄存器 地址偏移:0x80 复位值:0x0000 0000
} ADC_Type;
typedef enum IRQn
{
/* interruput numbers */
WWDGT_IRQn = 0, /*!<看门狗定时器中断 */
RCU_CTC_IRQn = 5, /*!< RCU_BASE and CTC interrupt */
ADC0_1_IRQn = 18, /*!< ADC0 and ADC1 interrupt */
}IRQn_Type;
/* 总线映射 */
#define APB1_BUS_BASE ((uint32_t)0x40000000U)
#define APB2_BUS_BASE ((uint32_t)0x40010000U)
#define AHB1_BUS_BASE ((uint32_t)0x40018000U)
#define AHB3_BUS_BASE ((uint32_t)0x60000000U)
/* APB2内存映射 */
#define ADC_BASE (APB2_BUS_BASE + 0x00002400U)
/* ADC寄存器地址偏移 */
/* ADC0基地址:0x4001 2400
* ADC1基地址:0x4001 2800
* ADC2基地址:0x4001 3C00*/
#define ADC0_BASE (ADC_BASE + 0x00000000U)
#define ADC1_BASE (ADC_BASE + 0x00000400U)
//#if (defined(GD32F30X_HD) || defined(GD32F30X_XD))
#define ADC2_BASE (ADC_BASE + 0x00001800U)
#define ADC0 ((ADC_Type *)(ADC0_BASE))
#define ADC1 ((ADC_Type *)(ADC1_BASE))
#define ADC2 ((ADC_Type *)(ADC2_BASE))
#define ADC_BASES {ADC0, ADC1, ADC2}
#define BUTTON_SAMPLE_CNT 11
#define CHECK_BY_AD 1 //1以AD值方式对比,0以电压方式对比
typedef enum /* 等号左边为电磁阀管路图编号 */
{ /* 右边数字为原理图中的电磁阀编号 ,0表示没有使用到 */
V101 = 1,
V102 = 2,
V103 = 3,
V104 = 4,
V105 = 5,
V106 = 6,
V107 = 7,
V108 = 8,
V109 = 9,
V110 = 10,
V201 = 11,
V202 = 12,
V203 = 13,
V204 = 14,
V205 = 15,
V206 = 16,
V207 = 17,
V208 = 18,
V209 = 19,
V210 = 20,
V301 = 21,
V302 = 22,
V303 = 23,
V304 = 24,
V305 = 25,
V306 = 26,
V307 = 27,
V308 = 28,
V309 = 29,
V310 = 30,
V401 = 31,
V402 = 32,
V403 = 33,
V404 = 34,
V405 = 35,
V406 = 36,
V407 = 37,
V408 = 38,
V409 = 39,
V410 = 40,
} e_Vxxx;
void Adc0_Init(void);
void Adc0_GetRSQVal(uint16_t *array, uint8_t offset, uint8_t len);
void RB_ADC_Init(void);
void RB_ADC_ScanButton(void);
void Fun_BubbleSort(uint16_t *array, uint8_t len, uint8_t sort_dir);
void RB_ADC_ScanButton2(void);
#ifdef __cplusplus
}
#endif
#endif // CTRL_ADC_H
【2】ctrl_adc.h [重点]
#ifndef CTRL_ADC_H
#define CTRL_ADC_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdio.h>
#define __IO volatile //值可以被改变 每次必须从内存获取值 防止被编译器优化
#define __I volatile const //值不希望被改变,保持这个值为只读常量
#define __STATIC_INLINE static inline //内敛函数 适用代码短的函数
#if defined(__CC_ARM)
#pragma anon_unions //keil中默认是不支持匿名结构体的,需要编译指令#pragma anon_unions指名。
#elif defined(CCARM__)
#pragma language=extended //IAR对所用语言(这里是C)做的一些扩展,也就是说这里可以用扩展的功能
#elif defined (__ICCARM__)
/* anonymous unions are enabled by default:默认启用匿名联合 */
#elif defined(__GNUC__)
/* anonymous unions are enabled by default */
#elif defined(__TMS470__)
/* anonymous unions are enabled by default */
#elif defined(__TASKING__)
#pragma warning 586
#else
#warning Not supported compiler type //警告不支持编译器类型
#endif
/*============================控制MCU部分==========================*/
/* 通道号 */
#define ADC_CHANNEL_0 0x00
#define ADC_CHANNEL_1 0x01
#define ADC_CHANNEL_2 0x02
#define ADC_CHANNEL_3 0x03
#define ADC_CHANNEL_4 0x04
#define ADC_CHANNEL_5 0x05
#define ADC_CHANNEL_6 0x06
#define ADC_CHANNEL_7 0x07
#define ADC_CHANNEL_8 0x08
#define ADC_CHANNEL_9 0x09
#define ADC_CHANNEL_10 0x0A
#define ADC_CHANNEL_11 0x0B
#define ADC_CHANNEL_12 0x0C
#define ADC_CHANNEL_13 0x0D
#define ADC_CHANNEL_14 0x0E
#define ADC_CHANNEL_15 0x0F
#define ADC_CHANNEL_16 0x10
#define ADC_CHANNEL_17 0x11
/* 规则组长度 ADC_RSQ0.Bits.RL */
#define REGULAR_LEN_1 0x00
#define REGULAR_LEN_2 0x01
#define REGULAR_LEN_3 0x02
#define REGULAR_LEN_4 0x03
#define REGULAR_LEN_5 0x04
#define REGULAR_LEN_6 0x05
#define REGULAR_LEN_7 0x06
#define REGULAR_LEN_8 0x07
#define REGULAR_LEN_9 0x08
#define REGULAR_LEN_10 0x09
#define REGULAR_LEN_11 0x0A
#define REGULAR_LEN_12 0x0B
#define REGULAR_LEN_13 0x0C
#define REGULAR_LEN_14 0x0D
#define REGULAR_LEN_15 0x0E
#define REGULAR_LEN_16 0x0F
/*注入组长度 注入通道,x=0,1,2,3 数据偏移值,取值范围为0~4095*/
#define INSERTED_LEN_1 0x00
#define INSERTED_LEN_2 0x01
#define INSERTED_LEN_3 0x02
#define INSERTED_len_4 0x03
/*ADC的采样时间*/
#define ADC_SAMPLETIME_1POINT5 //1.5 周期
#define ADC_SAMPLETIME_7POINT5 //7.5 周期
#define ADC_SAMPLETIME_13POINT5 //13.5 周期
#define ADC_SAMPLETIME_28POINT5 //28.5 周期
#define ADC_SAMPLETIME_41POINT5 //41.5 周期
#define ADC_SAMPLETIME_55POINT5 //55.5 周期
#define ADC_SAMPLETIME_71POINT5 //71.5 周期
#define ADC_SAMPLETIME_239POINT5 //239.5 周期
/*ADC 分辨率*/
#define ADC_RESOLUTION_12B //12位
#define ADC_RESOLUTION_10B //10位
#define ADC_RESOLUTION_8B //8位
#define ADC_RESOLUTION_6B //6位
/*ADC 通道组*/ //间断模式下的转换数目,规则通道组取值为1..8,注入通道组取值无意义
//ADC通道选择ADC_CHANNEL_x(x=0..17) ADC 通道x (x=0..17)(只有ADC0,可取值x=16和17 )
#define ADC_REGULAR_CHANNEL //规则通道组
#define ADC_INSERTED_CHANNEL//注入通道组
/*ADC 运行模式*/
#define ADC_MODE_FREE //所有ADC运行于独立模式
#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL //ADC0和ADC1运行在规则并行+注入并行组合模式
#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION //ADC0和ADC1运行在规则并行+交替触发组合模式
#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST //ADC0和ADC1运行在注入并行+快速交叉组合模式
#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW //ADC0和ADC1运行在注入并行+慢速交叉组合模式
#define ADC_DAUL_INSERTED_PARALLEL //ADC0和ADC1运行在注入并行模式
#define ADC_DAUL_REGULAL_PARALLEL //ADC0和ADC1运行在规则并行模式
#define ADC_DAUL_REGULAL_FOLLOWUP_FAST //ADC0和ADC1运行在快速交叉模式
#define ADC_DAUL_REGULAL_FOLLOWUP_SLOW //ADC0和ADC1运行在慢速交叉模式
#define ADC_DAUL_INSERTED_TRRIGGER_ROTATION //ADC0和ADC1运行在交替触发模式
/*ADC 功能配置*/
#define ADC_SCAN_MODE //扫描模式选择
#define ADC_INSERTED_CHANNEL_AUTO //注入组自动转换
#define ADC_CONTINUOUS_MODE //连续模式选择
/*ADC 规则通道组或注入通道组触发源*/
#define ADC0_1_EXTTRIG_REGULAR_T0_CH0 //TIMER0 CH0事件(规则组)
#define ADC0_1_EXTTRIG_REGULAR_T0_CH1 //TIMER0 CH1事件(规则组)
#define ADC0_1_EXTTRIG_REGULAR_T0_CH2 //TIMER0 CH2事件(规则组)
#define ADC0_1_EXTTRIG_REGULAR_T1_CH1 //TIMER1 CH1事件(规则组)
#define ADC0_1_EXTTRIG_REGULAR_T2_TRGO //TIMER2TRGO事件(规则组)
#define ADC0_1_EXTTRIG_REGULAR_T3_CH3 //TIMER3 CH3事件(规则组)
#define ADC0_1_EXTTRIG_REGULAR_T7_TRGO //TIMER7 TRGO事件(规则组)
#define ADC0_1_EXTTRIG_REGULAR_EXTI_11 //外部中断线11(规则组)
#define ADC2_EXTTRIG_REGULAR_T2_CH0 //TIMER2 CH0事件(规则组)
#define ADC2_EXTTRIG_REGULAR_T1_CH2 //TIMER1 CH2事件(规则组)
#define ADC2_EXTTRIG_REGULAR_T0_CH2 //TIMER0 CH2事件(规则组)
#define ADC2_EXTTRIG_REGULAR_T7_CH0 //TIMER7CH0事件(规则组)
#define ADC2_EXTTRIG_REGULAR_T7_TRGO //TIMER7 TRGO事件(规则组)
#define ADC2_EXTTRIG_REGULAR_T4_CH0 //TIMER4 CH0事件(规则组)
#define ADC2_EXTTRIG_REGULAR_T4_CH2 //TIMER4 CH2事件(规则组)
#define ADC0_1_2_EXTTRIG_REGULAR_NONE //软件触发(规则组)
#define ADC0_1_EXTTRIG_INSERTED_T0_TRGO //TIMER0 TRGO事件(注入组)
#define ADC0_1_EXTTRIG_INSERTED_T0_CH3 //TIMER0 CH3事件(注入组)
#define ADC0_1_EXTTRIG_INSERTED_T1_TRGO //TIMER1 TRGO事件(注入组)
#define ADC0_1_EXTTRIG_INSERTED_T1_CH0 //TIMER1 CH0事件(注入组)
#define ADC0_1_EXTTRIG_INSERTED_T2_CH3 //TIMER2 CH3事件(注入组)
#define ADC0_1_EXTTRIG_INSERTED_T3_TRGO //TIMER3 TRGO事件(注入组)
#define ADC0_1_EXTTRIG_INSERTED_EXTI_15 //外部中断线15 (注入组)
#define ADC0_1_EXTTRIG_INSERTED_T7_CH3 //TIMER7 CH3事件(注入组)
#define ADC2_EXTTRIG_INSERTED_T0_TRGO //TIMER0 TRGO事件(注入组)
#define ADC2_EXTTRIG_INSERTED_T0_CH3 //TIMER0 CH3事件(注入组)
#define ADC2_EXTTRIG_INSERTED_T3_CH2 //TIMER3 CH2事件(注入组)
#define ADC2_EXTTRIG_INSERTED_T7_CH1 //TIMER7 CH1事件(注入组)
#define ADC2_EXTTRIG_INSERTED_T7_CH3 //TIMER7 CH3事件(注入组)
#define ADC2_EXTTRIG_INSERTED_T4_TRGO //TIMER4 TRGO事件(注入组)
#define ADC2_EXTTRIG_INSERTED_T4_CH3 //TIMER4 CH3事件(注入组)
#define ADC0_1_2_EXTTRIG_INSERTED_NONE //软件触发(注入组)
/*ADC标志位*/
#define ADC_FLAG_WDE //模拟看门狗事件标志位
#define ADC_FLAG_EOC //转换结束标志位
#define ADC_FLAG_EOIC //注入通道组转换结束标志位
#define ADC_FLAG_STIC //注入通道组转换开始标志位
#define ADC_FLAG_STRC //规则通道组转换开始标志位
/*ADC过采样触发模式*/
#define ADC_OVERSAMPLING_ALL_CONVERT //在一个触发之后,对一个通道连续进行过采样转换
#define ADC_OVERSAMPLING_ONE_CONVERT //在一个触发之后,对一个通道只进行一次过采样转换
typedef struct {
union{
struct//ADC标志位 从低位->高位
{ //WDE-》转换电压超过ADC_WDLT和ADC_WDHT寄存器设定的阈值时由硬件置1,软件写0清除。
__IO uint32_t WDE :1; //模拟看门狗事件 1:产生模拟看门狗事件 0:没有模拟看门狗事件
__IO uint32_t EOC :1; //组转换结束 1:转化结束 0:未结束转化 转化结束时硬件会置1 软件写0清除或读ADC_RDATA寄存器清除
__IO uint32_t EOIC :1; //注入通道组转换结束 1:转化结束 0:未结束转化 转化结束时硬件会置1 软件写0清除
__IO uint32_t STIC :1; //注入通道组转换开始 1:开始转化 0:未开启转化 转化开始时硬件会置1 软件写0清除
__IO uint32_t STRC :1; //规则通道组转换开始 1:开始转化 0:未开启转化 转化开始时硬件会置1 软件写0清除
__IO uint32_t :27; //保留 必须保留复位值
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 C000 -》0000 0000 0000 0000 1100 0000 0000 0000 (32位)
}ADC_STAT; // 地址偏移: 0x00 状态寄存器
union{
struct
{
__IO uint32_t WDCHSEL :5; //模拟看门狗通道选择
/*
* 00000: ADC 通道 0
00001: ADC 通道 1
00010: ADC 通道 2
00011: ADC 通道 3
00100: ADC 通道 4
00101: ADC 通道 5
00110: ADC 通道 6
00111: ADC 通道 7
01000: ADC 通道 8
01001: ADC 通道 9
01010: ADC 通道 10
01011: ADC 通道 11
01100: ADC 通道 12
01101: ADC 通道 13
01110: ADC 通道 14
01111: ADC 通道 15
10000: ADC 通道 16
10001: ADC 通道 17
其他值保留
注意: ADC0 的模拟输入通道 16 和通道 17 分别连接到温度传感器和 VREFINT。
ADC1 的模拟输入通道 16 和通道 17 内部都连接到 VSSA。 ADC2 的模拟输入通道
16 和通道 17 内部都连接到 VSSA。
*/
__IO uint32_t EOCIE :1; //EOC中断使能 0:EOC 中断禁止 1:EOC 中断使能
__IO uint32_t WDEIE :1; //模拟看门狗事件 中断使能 0:WDE 中断禁止 1:WDE 中断使能
__IO uint32_t EOICIE :1; //EOIC 中断使能 0:禁止 1:使能
__IO uint32_t SM :1; //扫描转换模式 0:禁止 1:使能
__IO uint32_t WDSC :1; //扫描模式下,模拟看门狗在单通道有效 0:模拟看门狗在所有通道有效 1:模拟看门狗在单通道有效
__IO uint32_t ICA :1; //注入组自动转换 0:禁止 1:使能
__IO uint32_t DISRC :1; //规则组间断模式 0:禁止 1:使能
__IO uint32_t DISIC :1; //注入组间断模式 0:禁止 1:使能
__IO uint32_t DISNUM :3; //间断模式下的转换数目 触发后即将被转换的通道数目将变成 DISNUM[2:0]+1
__IO uint32_t SYNCM :4; //ADC 同步模式选择 0000:独立模式
/*
0000:独立模式
0001:规则并行+注入并行组合模式
0010:规则并行+交替触发组合模式
0011:注入并行+快速交叉组合模式
0100:注入并行+慢速交叉组合模式
0101:注入并行模式
0110:规则并行模式
0111:快速交叉模式
1000:慢速交叉模式
1001:交替触发模式
注意:在 ADC1 和 ADC2 中这些位为保留位。在同步模式下,改变通道的配置会产
生一个重新开始的条件,会导致同步丢失,建议在任何配置之前关闭同步模式。
*/
__IO uint32_t :2;
__IO uint32_t IWDEN :1;//注入组看门狗使能 0:禁止 1:使能
__IO uint32_t RWDEN :1;//规则组看门狗使能 0:禁止 1:使能
__IO uint32_t :8;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_CTL0; // 地址偏移: 0x04 控制寄存器 0
union{
struct
{
__IO uint32_t ADCON :1; //ADC 上电使能位 0:禁止 ADC 关闭电源 1:使能 ADC
/*开启 ADC。该位从‘0’变成‘1’将在稳定时间结束后唤醒 ADC。当该位被置位以后,不
改变寄存器的其他位仅仅对该位写‘1’, 将开启转换。*/
__IO uint32_t CTN :1; //0:禁止连续模式,1:使能连续模式
__IO uint32_t CLB :1; /* ADC 校准 : 0:校准结束 1:校准开始 */
__IO uint32_t RSTCLB :1; /* 校准复位: 软件置位(1), 在校准寄存器初始化后该位硬件清零 0:校准结束 1:校准开始*/
__IO uint32_t :4; //7:4 保留 必须保持复位值。
__IO uint32_t DMA :1; //DMA 请求使能 0:禁止 1:使能
__IO uint32_t :2; //10:9 保留 必须保持复位值。
__IO uint32_t DAL :1; //数据对齐 0:最低有效位对齐 1:最高有效位对齐
__IO uint32_t ETSIC :3; //注入组外部触发选择
/*14:12 ETSIC[2:0]
对于 ADC0 与 ADC1:
000:定时器 0 TRGO
001:定时器 0 CH3
010:定时器 1 TRGO
011:定时器 1 CH0
100:定时器 2 CH3
101:定时器 3 TRGO
110:中断线 15/定时器 7 CH3
111:软件触发
对于 ADC2:
000:定时器 0 TRGO
001:定时器 0 CH3
010:定时器 3 CH2
011:定时器 7 CH1
100:定时器 7 CH3
101:定时器 4 TRGO
110:定时器 4 CH3
111:软件触发
*/
__IO uint32_t ETEIC :1; //注入组外部触发使能 0:禁止 1:使能
__IO uint32_t :1; //必须保持复位值。
__IO uint32_t ETSRC :3; //规则组外部触发选择: 111:软件触发
/*19:17 ETSRC[2:0]
对于 ADC0 与 ADC1:
000:定时器 0 CH0
001:定时器 0 CH1
010:定时器 0 CH2
011:定时器 1 CH1
100:定时器 2 TRGO
101:定时器 3 CH3
110:中断线 11/定时器 7 TRGO
111:软件触发
对于 ADC2:
000:定时器 2 CH0
001:定时器 1 CH2
010:定时器 0 CH2
011:定时器 7 CH0
100:定时器 7 TRGO
101:定时器 4 CH0
110:定时器 4 CH2
111:软件触发
*/
__IO uint32_t ETERC :1; //规则组外部触发使能 0:禁止 1:使能
__IO uint32_t SWICST :1; //注入组转换开始: 如果 ETSRC 是 111,该位置‘1’开启规则组转换。软件置位,软件清零,或转换开始后,由硬件清零
__IO uint32_t SWRCST :1; //规则组转换开始: 如果 ETSIC 是 111,该位置‘1’开启注入组转换。软件置位,软件清零,或转换开始后,由硬件清零
__IO uint32_t TSVREN :1; // 将ADC_CTL1 寄存器的 TSVREN 位置 1可以使能温度传感器通道(ADC0_CH16)和 VREFINT通道(ADC0_CH17)。
__IO uint32_t :8; //保留 必须保持复位值
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_CTL1; // 地址偏移: 0x08 控制寄存器 1
union{
struct
{
__IO uint32_t SPT10 :3;//通道采样时间
/*
000:1.5 周期
001:7.5 周期
010:13.5 周期
011:28.5 周期
100:41.5 周期
101:55.5 周期
110:71.5 周期
111:239.5 周期
*/
__IO uint32_t SPT11 :3;//参考 SPT10[2:0]的描述
__IO uint32_t SPT12 :3;//参考 SPT10[2:0]的描述
__IO uint32_t SPT13 :3;//参考 SPT10[2:0]的描述
__IO uint32_t SPT14 :3;//参考 SPT10[2:0]的描述
__IO uint32_t SPT15 :3;//参考 SPT10[2:0]的描述
__IO uint32_t SPT16 :3;//参考 SPT10[2:0]的描述
__IO uint32_t SPT17 :3;//参考 SPT10[2:0]的描述
__IO uint32_t :8;//31:24 保留 必须保持复位值。
}Bits; 0000 0000 1111 1111 1111 1111 11111 1111
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_SAMPT0; // 地址偏移: 0x0C 采样时间寄存器 0
union{
struct
{
__IO uint32_t SPT0 :3;//通道采样时间
/*
000:1.5 周期
001:7.5 周期
010:13.5 周期
011:28.5 周期
100:41.5 周期
101:55.5 周期
110:71.5 周期
111:239.5 周期
*/
__IO uint32_t SPT1 :3;//参考 SPT0[2:0]的描述
__IO uint32_t SPT2 :3;//参考 SPT0[2:0]的描述
__IO uint32_t SPT3 :3;//参考 SPT0[2:0]的描述
__IO uint32_t SPT4 :3;//参考 SPT0[2:0]的描述
__IO uint32_t SPT5 :3;//参考 SPT0[2:0]的描述
__IO uint32_t SPT6 :3;//参考 SPT0[2:0]的描述
__IO uint32_t SPT7 :3;//参考 SPT0[2:0]的描述
__IO uint32_t SPT8 :3;//参考 SPT0[2:0]的描述
__IO uint32_t SPT9 :3;//参考 SPT0[2:0]的描述
__IO uint32_t :2;//31:30 保留 必须保持复位值。
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_SAMPT1; // 地址偏移: 0x10 采样时间寄存器 1
union{
struct
{
__IO uint32_t IOFF :12;//注入通道 x 的数据偏移
/*当转换注入通道时,这些位定义了用于从原始转换数据中减去的数值。转换的结果
可以在 ADC_IDATAx 寄存器中读出。*/
__IO uint32_t :20;//31:12 保留 必须保持复位值。
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_IOFF0; // 地址偏移: 0x14 注入通道数据偏移寄存器 0
union{
struct
{
__IO uint32_t IOFF :12;
__IO uint32_t :20;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_IOFF1; // 地址偏移: 0x18 注入通道数据偏移寄存器 1
union{
struct
{
__IO uint32_t IOFF :12;
__IO uint32_t :20;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_IOFF2; // 地址偏移: 0x1C 注入通道数据偏移寄存器 2
union{
struct
{
__IO uint32_t IOFF :12;
__IO uint32_t :20;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_IOFF3; // 地址偏移: 0x20 注入通道数据偏移寄存器 3
union{
struct
{
__IO uint32_t WDHT :12;//模拟看门狗高阈值
__IO uint32_t :20;//31:12 保留 必须保持复位值。
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_WDHT; // 地址偏移: 0x24 看门狗高阈值寄存器 模拟看门狗高阈值,0..4095
union{
struct
{
__IO uint32_t WDLT :12;//模拟看门狗低阈值 这些位定义了模拟看门狗的低阈值。
__IO uint32_t :20;//31:12 保留 必须保持复位值。
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_WDLT; // 地址偏移: 0x28 看门狗低阈值寄存器 模拟看门狗低阈值,0..4095
union{
struct
{
__IO uint32_t RSQ12 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ13 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ14 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ15 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RL :4;//规则组长度,0-F表示1-16个 规则通道转换序列中的总的通道数目为 RL[3:0]+1。
__IO uint32_t :8;//31:24 保留 必须保持复位值。
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_RSQ0; // 地址偏移: 0x2C 规则序列寄存器 0
union{
struct
{
__IO uint32_t RSQ6 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ7 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ8 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ9 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ10 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ11 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t :2;//31:30 保留 必须保持复位值。
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_RSQ1; // 地址偏移: 0x30 规则序列寄存器 1
union{
struct
{
__IO uint32_t RSQ0 :5;//通道编号(0..17)写入这些位来选择规则通道的第 n 个转换的通道
__IO uint32_t RSQ1 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ2 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ3 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ4 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t RSQ5 :5;//参考 RSQ0[4:0]的描述
__IO uint32_t :2;//31:30 保留 必须保持复位值。
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_RSQ2; // 地址偏移: 0x34 规则序列寄存器 2
union{
struct
{
__IO uint32_t ISQ0 :5;//通道编号(0..17)写入这些位来选择注入组的第 n 个转换的通道
/*
和规则通道转换序列不同的是,如果 IL[1:0]长度不足 4,注入通道转换从(4-IL[1:0]-
1) 开始。
IL 注入通道转换顺序
3 ISQ0 >> ISQ1 >> ISQ2 >> ISQ3
2 ISQ1 >> ISQ2 >> ISQ3
1 ISQ2 >> ISQ3
0 ISQ3
*/
__IO uint32_t ISQ1 :5;//参考 ISQ0[4:0]的描述
__IO uint32_t ISQ2 :5;//参考 ISQ0[4:0]的描述
__IO uint32_t ISQ3 :5;//参考 ISQ0[4:0]的描述
__IO uint32_t IL :2;//注入序列长度 注入组总的通道数目为 IL[1:0]+1。
__IO uint32_t :10;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}ADC_ISQ; // 地址偏移: 0x38 注入序列寄存器
union{
struct
{
__I uint32_t IDATAn :16;//注入转换的数据 n 这些位包含了注入通道的转换结果,只读。
__I uint32_t :16;
}Bits;
__I uint32_t Byte; // 复位值: 0x0000 0000
}ADC_IDATA0; // 地址偏移: 0x3C 注入数据寄存器 0
union{
struct
{
__I uint32_t IDATAn :16;//注入转换的数据 n 这些位包含了注入通道的转换结果,只读。
__I uint32_t :16;
}Bits;
__I uint32_t Byte; // 复位值: 0x0000 0000
}ADC_IDATA1; // 地址偏移: 0x40 注入数据寄存器 1
union{
struct
{
__I uint32_t IDATAn :16;//注入转换的数据 n 这些位包含了注入通道的转换结果,只读。
__I uint32_t :16;
}Bits;
__I uint32_t Byte; // 复位值: 0x0000 0000
}ADC_IDATA2; // 地址偏移: 0x44 注入数据寄存器 2
union{
struct
{
__I uint32_t IDATAn :16;//注入转换的数据 n 这些位包含了注入通道的转换结果,只读。
__I uint32_t :16;
}Bits;
__I uint32_t Byte; // 复位值: 0x0000 0000
}ADC_IDATA3; // 地址偏移: 0x48 注入数据寄存器 3
union{
struct
{
__I uint32_t RDATA :16; //规则通道数据 这些位包含了规则通道的转换结果,只读。
/*ADC0:在同步模式下,这些位包含着 ADC1 的规则通道数据
ADC1 和 ADC2:这些位没有使用.*/
__I uint32_t ADC1RDTR :16; //规则通道数据 ADC1
}Bits;
__I uint32_t Byte; // 复位值: 0x0000 0000
}ADC_RDATA; // 地址偏移: 0x4C 规则数据寄存器
/*============================================================================*/
//注意:当 ADCON= 0 时软件才允许写该位(确定没有转换正在进行) 本次项目禁用这项
union{
struct{
__IO uint32_t OVSEN :1; //过滤采样使能 0:过滤采样失能 1:过滤采样使能 注意:当 ADCON=0 时软件才允许写该位(确定没有转换正在进行)
__IO uint32_t :1; //1 保留 必须保持复位值。
__IO uint32_t OVSR :3; //过采样率
/*
这些位定义了过采样率的大小.
000:2x
001:4x
010:8x
011:16x
100:32x
101:64x
110:128x
111:256x
注意:当 ADCON=0 时软件才允许写该位(确定没有转换正在进行)
*/
__IO uint32_t OVSS :4; //过滤采样移位
/*
该位通过软件设置和清除.
0000:不移位
0001:移 1 位
0010:移 2 位
0011:移 3 位
0100:移 4 位
0101:移 5 位
0110:移 6 位
0111:移 7 位
1000:移 8 位
其他保留
注意:当 ADCON=0 时软件才允许写该位(确定没有转换正在进行).
*/
__IO uint32_t TOVS :1; //触发过滤采样
/*该位通过软件设置和清除.
0:所有的过滤采样连续转换完成一个触发后
1:对于过采样通道的每次转换都需要一次触发,触发次数由过采样率
(OVSR[2:0])决定。
注意:当 ADCON= 0 时软件才允许写该位(确定没有转换正在进行).*/
__IO uint32_t :2;
__IO uint32_t DRES :2; //ADC 分辨率
/*13:12 DRES[1:0] ADC 分辨率
ADC 分辨率
00:12 位
01:10 位
10:8 位
11:6 位
*/
__IO uint32_t :18;
}Bits;
__I uint32_t Byte;
}ADC_OVSAMPCTL;//过采样控制寄存器 地址偏移:0x80 复位值:0x0000 0000
} ADC_Type;
typedef enum IRQn
{
/* interruput numbers */
WWDGT_IRQn = 0, /*!<看门狗定时器中断 */
RCU_CTC_IRQn = 5, /*!< RCU_BASE and CTC interrupt */
ADC0_1_IRQn = 18, /*!< ADC0 and ADC1 interrupt */
}IRQn_Type;
/* 总线映射 */
#define APB1_BUS_BASE ((uint32_t)0x40000000U)
#define APB2_BUS_BASE ((uint32_t)0x40010000U)
#define AHB1_BUS_BASE ((uint32_t)0x40018000U)
#define AHB3_BUS_BASE ((uint32_t)0x60000000U)
/* APB2内存映射 */
#define ADC_BASE (APB2_BUS_BASE + 0x00002400U)
/* ADC寄存器地址偏移 */
/* ADC0基地址:0x4001 2400
* ADC1基地址:0x4001 2800
* ADC2基地址:0x4001 3C00*/
#define ADC0_BASE (ADC_BASE + 0x00000000U)
#define ADC1_BASE (ADC_BASE + 0x00000400U)
//#if (defined(GD32F30X_HD) || defined(GD32F30X_XD))
#define ADC2_BASE (ADC_BASE + 0x00001800U)
#define ADC0 ((ADC_Type *)(ADC0_BASE))
#define ADC1 ((ADC_Type *)(ADC1_BASE))
#define ADC2 ((ADC_Type *)(ADC2_BASE))
#define ADC_BASES {ADC0, ADC1, ADC2}
#define BUTTON_SAMPLE_CNT 11
#define CHECK_BY_AD 1 //1以AD值方式对比,0以电压方式对比
typedef enum /* 等号左边为电磁阀管路图编号 */
{ /* 右边数字为原理图中的电磁阀编号 ,0表示没有使用到 */
V101 = 1,
V102 = 2,
V103 = 3,
V104 = 4,
V105 = 5,
V106 = 6,
V107 = 7,
V108 = 8,
V109 = 9,
V110 = 10,
V201 = 11,
V202 = 12,
V203 = 13,
V204 = 14,
V205 = 15,
V206 = 16,
V207 = 17,
V208 = 18,
V209 = 19,
V210 = 20,
V301 = 21,
V302 = 22,
V303 = 23,
V304 = 24,
V305 = 25,
V306 = 26,
V307 = 27,
V308 = 28,
V309 = 29,
V310 = 30,
V401 = 31,
V402 = 32,
V403 = 33,
V404 = 34,
V405 = 35,
V406 = 36,
V407 = 37,
V408 = 38,
V409 = 39,
V410 = 40,
} e_Vxxx;
void Adc0_Init(void);
void Adc0_GetRSQVal(uint16_t *array, uint8_t offset, uint8_t len);
void RB_ADC_Init(void);
void RB_ADC_ScanButton(void);
void Fun_BubbleSort(uint16_t *array, uint8_t len, uint8_t sort_dir);
void RB_ADC_ScanButton2(void);
#ifdef __cplusplus
}
#endif
#endif // CTRL_ADC_H
【3】gd32f30x_dma_reg.h [参考]
DMA寄存器不是本节重点,后面会学到,这里主要用于和ADC的规则数据寄存器RDATA和注入数据寄存器IDATA配合处理采集的ADC数据
#ifndef GD32F30X_DMA_REG_H
#define GD32F30X_DMA_REG_H
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <stdint.h>
/**
******************************************************************************
* @brief GD32F30x DMA寄存器地址映射、位域映射
******************************************************************************
*/
#ifndef _GD32F30X_DMA_REG_H_
#define _GD32F30X_DMA_REG_H_
#define __IO volatile //值可以被改变 每次必须从内存获取值 防止被编译器优化
#define __I volatile const //值不希望被改变,保持这个值为只读常量
#define __STATIC_INLINE static inline //内敛函数 适用代码短的函数
typedef struct {
union{
struct
{
__I uint32_t GIF0 :1;
__I uint32_t FTFIF0 :1;
__I uint32_t HTFIF0 :1;
__I uint32_t ERRIF0 :1;
__I uint32_t GIF1 :1;
__I uint32_t FTFIF1 :1;
__I uint32_t HTFIF1 :1;
__I uint32_t ERRIF1 :1;
__I uint32_t GIF2 :1;
__I uint32_t FTFIF2 :1;
__I uint32_t HTFIF2 :1;
__I uint32_t ERRIF2 :1;
__I uint32_t GIF3 :1;
__I uint32_t FTFIF3 :1;
__I uint32_t HTFIF3 :1;
__I uint32_t ERRIF3 :1;
__I uint32_t GIF4 :1;
__I uint32_t FTFIF4 :1;
__I uint32_t HTFIF4 :1;
__I uint32_t ERRIF4 :1;
__I uint32_t GIF5 :1;
__I uint32_t FTFIF5 :1;
__I uint32_t HTFIF5 :1;
__I uint32_t ERRIF5 :1;
__I uint32_t GIF6 :1;
__I uint32_t FTFIF6 :1;
__I uint32_t HTFIF6 :1;
__I uint32_t ERRIF6 :1;
__I uint32_t :4;
}Bits;
__I uint32_t Byte; // 复位值: 0x0000 0000
}DMA_INTF; // 地址偏移: 0x00 中断标志位寄存器
union{
struct
{
__IO uint32_t GIFC0 :1;
__IO uint32_t FTFIFC0 :1;
__IO uint32_t HTFIFC0 :1;
__IO uint32_t ERRIFC0 :1;
__IO uint32_t GIFC1 :1;
__IO uint32_t FTFIFC1 :1;
__IO uint32_t HTFIFC1 :1;
__IO uint32_t ERRIFC1 :1;
__IO uint32_t GIFC2 :1;
__IO uint32_t FTFIFC2 :1;
__IO uint32_t HTFIFC2 :1;
__IO uint32_t ERRIFC2 :1;
__IO uint32_t GIFC3 :1;
__IO uint32_t FTFIFC3 :1;
__IO uint32_t HTFIFC3 :1;
__IO uint32_t ERRIFC3 :1;
__IO uint32_t GIFC4 :1;
__IO uint32_t FTFIFC4 :1;
__IO uint32_t HTFIFC4 :1;
__IO uint32_t ERRIFC4 :1;
__IO uint32_t GIFC5 :1;
__IO uint32_t FTFIFC5 :1;
__IO uint32_t HTFIFC5 :1;
__IO uint32_t ERRIFC5 :1;
__IO uint32_t GIFC6 :1;
__IO uint32_t FTFIFC6 :1;
__IO uint32_t HTFIFC6 :1;
__IO uint32_t ERRIFC6 :1;
__IO uint32_t :4;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}DMA_INTC; // 地址偏移: 0x04 中断标志位清除寄存器
union{
struct
{
__IO uint32_t CHEN :1;
__IO uint32_t FTFIE :1;
__IO uint32_t HTFIE :1;
__IO uint32_t ERRIE :1;
__IO uint32_t DIR :1;
__IO uint32_t CMEN :1;
__IO uint32_t PNAGA :1;
__IO uint32_t MNAGA :1;
__IO uint32_t PWIDTH :2;
__IO uint32_t MWIDTH :2;
__IO uint32_t PRIO :2;
__IO uint32_t M2M :1;
__IO uint32_t :17;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}DMA_CH0CTL; // 地址偏移: 0x08 通道 0 控制寄存器
union{
struct
{
__IO uint32_t CNT :16;
__IO uint32_t :16;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}DMA_CH0CNT; // 地址偏移: 0x0C 通道 0 计数寄存器
__IO uint32_t DMA_CH0PADDR :32; // 地址偏移: 0x10 通道 0 外设基地址寄存器 复位值: 0x0000 0000
__IO uint32_t DMA_CH0MADDR :32; // 地址偏移: 0x14 通道 0 存储器基地址寄存器 复位值: 0x0000 0000
__IO uint32_t :32; // 地址偏移: 0x18
union{
struct
{
__IO uint32_t CHEN :1;
__IO uint32_t FTFIE :1;
__IO uint32_t HTFIE :1;
__IO uint32_t ERRIE :1;
__IO uint32_t DIR :1;
__IO uint32_t CMEN :1;
__IO uint32_t PNAGA :1;
__IO uint32_t MNAGA :1;
__IO uint32_t PWIDTH :2;
__IO uint32_t MWIDTH :2;
__IO uint32_t PRIO :2;
__IO uint32_t M2M :1;
__IO uint32_t :17;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}DMA_CH1CTL; // 地址偏移: 0x1C 通道 1 控制寄存器
union{
struct
{
__IO uint32_t CNT :16;
__IO uint32_t :16;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}DMA_CH1CNT; // 地址偏移: 0x20 通道 1 计数寄存器
__IO uint32_t DMA_CH1PADDR :32; // 地址偏移: 0x24 通道 1 外设基地址寄存器 复位值: 0x0000 0000
__IO uint32_t DMA_CH1MADDR :32; // 地址偏移: 0x28 通道 1 存储器基地址寄存器 复位值: 0x0000 0000
__IO uint32_t :32; // 地址偏移: 0x2C
union{
struct
{
__IO uint32_t CHEN :1;
__IO uint32_t FTFIE :1;
__IO uint32_t HTFIE :1;
__IO uint32_t ERRIE :1;
__IO uint32_t DIR :1;
__IO uint32_t CMEN :1;
__IO uint32_t PNAGA :1;
__IO uint32_t MNAGA :1;
__IO uint32_t PWIDTH :2;
__IO uint32_t MWIDTH :2;
__IO uint32_t PRIO :2;
__IO uint32_t M2M :1;
__IO uint32_t :17;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}DMA_CH2CTL; // 地址偏移: 0x30 通道 2 控制寄存器
union{
struct
{
__IO uint32_t CNT :16;
__IO uint32_t :16;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}DMA_CH2CNT; // 地址偏移: 0x34 通道 2 计数寄存器
__IO uint32_t DMA_CH2PADDR :32; // 地址偏移: 0x38 通道 2 外设基地址寄存器 复位值: 0x0000 0000
__IO uint32_t DMA_CH2MADDR :32; // 地址偏移: 0x3C 通道 2 存储器基地址寄存器 复位值: 0x0000 0000
__IO uint32_t :32; // 地址偏移: 0x40
union{
struct
{
__IO uint32_t CHEN :1;
__IO uint32_t FTFIE :1;
__IO uint32_t HTFIE :1;
__IO uint32_t ERRIE :1;
__IO uint32_t DIR :1;
__IO uint32_t CMEN :1;
__IO uint32_t PNAGA :1;
__IO uint32_t MNAGA :1;
__IO uint32_t PWIDTH :2;
__IO uint32_t MWIDTH :2;
__IO uint32_t PRIO :2;
__IO uint32_t M2M :1;
__IO uint32_t :17;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}DMA_CH3CTL; // 地址偏移: 0x44 通道 3 控制寄存器
union{
struct
{
__IO uint32_t CNT :16;
__IO uint32_t :16;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}DMA_CH3CNT; // 地址偏移: 0x48 通道 3 计数寄存器
__IO uint32_t DMA_CH3PADDR :32; // 地址偏移: 0x4C 通道 3 外设基地址寄存器 复位值: 0x0000 0000
__IO uint32_t DMA_CH3MADDR :32; // 地址偏移: 0x50 通道 3 存储器基地址寄存器 复位值: 0x0000 0000
__IO uint32_t :32; // 地址偏移: 0x54
union{
struct
{
__IO uint32_t CHEN :1;
__IO uint32_t FTFIE :1;
__IO uint32_t HTFIE :1;
__IO uint32_t ERRIE :1;
__IO uint32_t DIR :1;
__IO uint32_t CMEN :1;
__IO uint32_t PNAGA :1;
__IO uint32_t MNAGA :1;
__IO uint32_t PWIDTH :2;
__IO uint32_t MWIDTH :2;
__IO uint32_t PRIO :2;
__IO uint32_t M2M :1;
__IO uint32_t :17;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}DMA_CH4CTL; // 地址偏移: 0x58 通道 4 控制寄存器
union{
struct
{
__IO uint32_t CNT :16;
__IO uint32_t :16;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}DMA_CH4CNT; // 地址偏移: 0x5C 通道 4 计数寄存器
__IO uint32_t DMA_CH4PADDR :32; // 地址偏移: 0x60 通道 4 外设基地址寄存器 复位值: 0x0000 0000
__IO uint32_t DMA_CH4MADDR :32; // 地址偏移: 0x64 通道 4 存储器基地址寄存器 复位值: 0x0000 0000
__IO uint32_t :32; // 地址偏移: 0x68
union{
struct
{
__IO uint32_t CHEN :1;
__IO uint32_t FTFIE :1;
__IO uint32_t HTFIE :1;
__IO uint32_t ERRIE :1;
__IO uint32_t DIR :1;
__IO uint32_t CMEN :1;
__IO uint32_t PNAGA :1;
__IO uint32_t MNAGA :1;
__IO uint32_t PWIDTH :2;
__IO uint32_t MWIDTH :2;
__IO uint32_t PRIO :2;
__IO uint32_t M2M :1;
__IO uint32_t :17;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}DMA_CH5CTL; // 地址偏移: 0x6C 通道 5 控制寄存器
union{
struct
{
__IO uint32_t CNT :16;
__IO uint32_t :16;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}DMA_CH5CNT; // 地址偏移: 0x70 通道 5 计数寄存器
__IO uint32_t DMA_CH5PADDR :32; // 地址偏移: 0x74 通道 5 外设基地址寄存器 复位值: 0x0000 0000
__IO uint32_t DMA_CH5MADDR :32; // 地址偏移: 0x78 通道 5 存储器基地址寄存器 复位值: 0x0000 0000
__IO uint32_t :32; // 地址偏移: 0x7C
union{
struct
{
__IO uint32_t CHEN :1;
__IO uint32_t FTFIE :1;
__IO uint32_t HTFIE :1;
__IO uint32_t ERRIE :1;
__IO uint32_t DIR :1;
__IO uint32_t CMEN :1;
__IO uint32_t PNAGA :1;
__IO uint32_t MNAGA :1;
__IO uint32_t PWIDTH :2;
__IO uint32_t MWIDTH :2;
__IO uint32_t PRIO :2;
__IO uint32_t M2M :1;
__IO uint32_t :17;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}DMA_CH6CTL; // 地址偏移: 0x80 通道 6 控制寄存器
union{
struct
{
__IO uint32_t CNT :16;
__IO uint32_t :16;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}DMA_CH6CNT; // 地址偏移: 0x84 通道 6 计数寄存器
__IO uint32_t DMA_CH6PADDR :32; // 地址偏移: 0x88 通道 6 外设基地址寄存器 复位值: 0x0000 0000
__IO uint32_t DMA_CH6MADDR :32; // 地址偏移: 0x8C 通道 6 存储器基地址寄存器 复位值: 0x0000 0000
} DMA_Type;
/* 总线映射 */
#define AHB1_BUS_BASE ((uint32_t)0x40018000U)
/* AHB1内存映射 */
#define DMA_BASE (AHB1_BUS_BASE + 0x00008000U)
/* DMA寄存器地址偏移 */
#define DMA0_BASE (DMA_BASE + 0x00000000U)
#define DMA1_BASE (DMA_BASE + 0x00000400U)
#define DMA0 ((DMA_Type *)(DMA0_BASE))
#define DMA1 ((DMA_Type *)(DMA1_BASE))
#define DMA_BASES {DMA0, DMA1}
#endif
#endif // GD32F30X_DMA_REG_H
【4】mon_adc.h [参考 +1]
#ifndef ADC_H
#define ADC_H
#include "adc_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
/*============================监控MCU部分==========================*/
typedef void (*ADC_CallbackType)(void); ///< ADC回调函数指针
//静态函数指针数组 初始化函数指针类型的NULL
static ADC_CallbackType g_adcCallback[1] = {(ADC_CallbackType)NULL};
//ADC 输入通道
#define ADC_CHANNEL_AD0 0x0 ///< ADC input channel 0
#define ADC_CHANNEL_AD1 0x1 ///< ADC input channel 1
#define ADC_CHANNEL_AD2 0x2 ///< ADC input channel 2
#define ADC_CHANNEL_AD3 0x3 ///< ADC input channel 3
#define ADC_CHANNEL_AD4 0x4 ///< ADC input channel 4
#define ADC_CHANNEL_AD5 0x5 ///< ADC input channel 5
#define ADC_CHANNEL_AD6 0x6 ///< ADC input channel 6
#define ADC_CHANNEL_AD7 0x7 ///< ADC input channel 7
#define ADC_CHANNEL_AD8 0x8 ///< ADC input channel 8
#define ADC_CHANNEL_AD9 0x9 ///< ADC input channel 9
#define ADC_CHANNEL_AD10 0xa ///< ADC input channel 10
#define ADC_CHANNEL_AD11 0xb ///< ADC input channel 11
#define ADC_CHANNEL_AD12 0xc ///< ADC input channel 12
#define ADC_CHANNEL_AD13 0xd ///< ADC input channel 13
#define ADC_CHANNEL_AD14 0xe ///< ADC input channel 14
#define ADC_CHANNEL_AD15 0xf ///< ADC input channel 15
#define ADC_CHANNEL_AD16 0x10///< ADC input channel 16
#define ADC_CHANNEL_AD17 0x11///< ADC input channel 17
//ADC 输入通道带隙
#define ADC_CHANNEL_AD16_BANDGAP 0x10///< ADC input channel bandgap
//ADC 输入通道内部温度传感器
#define ADC_CHANNEL_AD17_TEMPSENSOR 0x11///< ADC input channel internal temperature sensor
//ADC 时钟除 num(1-16)
#define ADC_ADIV_DIVIDE_1 0x00///< ADC clock divide by 1
#define ADC_ADIV_DIVIDE_2 0x01///< ADC clock divide by 2
#define ADC_ADIV_DIVIDE_3 0x02///< ADC clock divide by 3
#define ADC_ADIV_DIVIDE_4 0x03///< ADC clock divide by 4
#define ADC_ADIV_DIVIDE_5 0x04///< ADC clock divide by 5
#define ADC_ADIV_DIVIDE_6 0x05///< ADC clock divide by 6
#define ADC_ADIV_DIVIDE_7 0x06///< ADC clock divide by 7
#define ADC_ADIV_DIVIDE_8 0x07///< ADC clock divide by 8
#define ADC_ADIV_DIVIDE_9 0x08///< ADC clock divide by 9
#define ADC_ADIV_DIVIDE_10 0x09///< ADC clock divide by 10
#define ADC_ADIV_DIVIDE_11 0x0A///< ADC clock divide by 11
#define ADC_ADIV_DIVIDE_12 0x0B///< ADC clock divide by 12
#define ADC_ADIV_DIVIDE_13 0x0C///< ADC clock divide by 13
#define ADC_ADIV_DIVIDE_14 0x0D///< ADC clock divide by 14
#define ADC_ADIV_DIVIDE_15 0x0E///< ADC clock divide by 15
#define ADC_ADIV_DIVIDE_16 0x0F///< ADC clock divide by 16
//ADC IDR 偏移值
#define IDR_Offset 0x3C
//ADC 注入通道选择 1-4
#define ADC_InjectedChannel_1 0x00///<Injected Channel1 selected
#define ADC_InjectedChannel_2 0x04///<Injected Channel2 selected
#define ADC_InjectedChannel_3 0x08///<Injected Channel3 selected
#define ADC_InjectedChannel_4 0x0C///<Injected Channel4 selected
//ADC 模拟监视器/监视器标志
#define ADC_FLAG_AMO 0x01///<Analog monitor/watchdog flag
//ADC 转换标志结束
#define ADC_FLAG_EOC 0x02///<End of conversion flag
//ADC 注入组转换标志结束
#define ADC_FLAG_IEOC 0x04///<End of injected group conversion flag
//ADC 转换数据右对齐
#define ADC_DataAlign_Right ((uint32_t)0x00)///<Conversion Data right alignment
//ADC 转换数据左对齐
#define ADC_DataAlign_Left ((uint32_t)0x01)///<Conversion Data left alignment
//ADC 转换触发源软件
#define ADC_TrigSource_Internal ((uint32_t)0x00)///<Conversion trig source software
//ADC 外部转换触发源
#define ADC_TrigSource_External ((uint32_t)0x01)///<Conversion trig source external
//ADC 监视器通道启用
#define ADC_AnalogWatchDog_SingleChannelEnable ((uint32_t)0x01)///<WatchDog Channel Enable
//ADC 监视器规则组启用
#define ADC_AnalogWatchDog_OnRegularEnable ((uint32_t)0x01)///<WatchDog Regular group Enable
//ADC 监视器注入组启用
#define ADC_AnalogWatchDog_OnInjectEnable ((uint32_t)0x01)///<WatchDog Inject group Enable
//ADC 监控器配置复位
#define AMO_SETTING_RESET (0xffffff1f)///<Monitor configt reset
//转换触发源复位
#define TRIG_SOURCE_SETTING_RESET (0xffcfffff)///<Conversion trig source reset
//ADC 转换模式复位
#define ADC_MODE_RESET (0xffff07ff)///<ADC Conversion Mode reset
//ADC 采样时间周期
#define ADC_SampleTime_6Cycle ((uint8_t)0x00)///<ADC Sample 6 Clock Cycle
#define ADC_SampleTime_14Cycle ((uint8_t)0x01)///<ADC Sample 14 Clock Cycle
#define ADC_SampleTime_29Cycle ((uint8_t)0x02)///<ADC Sample 29 Clock Cycle
#define ADC_SampleTime_42Cycle ((uint8_t)0x03)///<ADC Sample 42 Clock Cycle
#define ADC_SampleTime_56Cycle ((uint8_t)0x04)///<ADC Sample 56 Clock Cycle
#define ADC_SampleTime_72Cycle ((uint8_t)0x05)///<ADC Sample 72 Clock Cycle
#define ADC_SampleTime_215Cycle ((uint8_t)0x06)///<ADC Sample 215 Clock Cycle
#define ADC_SampleTime_3Cycle ((uint8_t)0x07)///<ADC Sample 3 Clock Cycle
//ADC 转换规则组单通道一次模式
#define ADC_Regular_Single_One_Mode ((uint8_t)0x01)///<ADC Conversion Regular Group Single Channel one times Mode
//ADC 转换规则组单通道连续模式
#define ADC_Regular_Single_Continous_Mode ((uint8_t)0x02)///<ADC Conversion Regular Group Single Channel continous Mode
//ADC 转换规则组多通道 通道和自动注入组一次模式
#define ADC_Regular_Multiple_One_Mode ((uint8_t)0x03)///<ADC Conversion Regular Group Multipe Channel and Auto Inject Group one time Mode
//ADC 转换规则组多通道一次模式
#define ADC_Regular_Multiple_AutoInject_Mode ((uint8_t)0x04)///<ADC Conversion Regular Group Multipe Channel one time Mode
//ADC 转换规则组多通道连续模式
#define ADC_Regular_Multiple_Continous_Mode ((uint8_t)0x05)///<ADC Conversion Regular Group Multipe Channel continous Mode
//ADC 转换规则组多通道 通道和自动注入组连续模式
#define ADC_Regular_Multiple_Continous_AutoInject_Mode ((uint8_t)0x06)///<ADC Conversion Regular Group Multipe Channel and Auto Inject Group continous Mode
//ADC 转换规则组多通道 通道通过中断一次性模式
#define ADC_Regular_Multiple_Discontinous_Mode ((uint8_t)0x07)///<ADC Conversion Regular Group Multipe Channel by Disnum one time Mode
//ADC 转换注入组通过中断一次性模式
#define ADC_Inject_Multiple_Discontinous_Mode ((uint8_t)0x08)///<ADC Conversion Inject Group by Disnum one time Mode
//ADC使能 不使能
#define ADC_ENABLE 1///<Set enable
#define ADC_DISABLE 0///<Set disable
//外设时钟控制使能
#define PERI_CLK_EN_0 0x40000004
#define PERI_CLK_EN_1 0x40000008
//外设软件复位失效
#define PERI_SFT_RST1 0x40000018
#define PERI_SFT_RST2 0x4000001c
//虚假替换 实际值不知
#define CLK_ADC 0x40080000
#define SRST_ADC 0x40084000
typedef struct {
uint32_t dataAlign; ///< Data Alignment: 0 Right alignment; 1 left alignment
uint32_t scanMode; ///< 常规和注入组的扫描模式已启用/禁用
uint32_t continousMode; ///< 启用/禁用连续模式
uint32_t disContinousModeOnRegularGroup; ///< 规则组的间断模式
uint32_t disContinousModeOnInjectGroup; ///< 注入组的间断模式
uint32_t injectAutoMode; ///< 注入组的反运动模式
uint32_t discNum; ///< 间断的模式,连续的数量
} ADC_InitType;
typedef struct {
uint32_t regularTrigSource; ///< 规则组选择内部或外部触发器源
uint32_t injectTrigSource; ///< 注入组选择内部或外部触发器源
} ADC_TrigSourceType;
typedef struct {
uint32_t analogWatchDogSingleMode; ///< 选择监视器单通道模式
uint32_t analogWatchDogOnRegularGroup; ///< 选择监视器的齿轮组模式
uint32_t analogWatchDogOnInjectGroup; ///< 选择监视器注入组模式
uint32_t analogWatchDogChannel; ///< 选择监视器adc通道
} ADC_AnalogWatchDogType;
void ADC_DMAInit(void);
void ADC_Init(void);
void ADC_Deinit(void) ;
uint32_t GetAdcChannelValue(uint32_t Channel); //设置AD转换通道,同时获取转换值
void ADC_IRQHandler(void);//中断服务函数
#endif // ADC_H
【5】rcu.h [参考]
#ifndef RCU_H
#define RCU_H
// GD32F30x 复位和时钟单元RCU寄存器地址映射、位域映射
#include <stdint.h>
#define __IO volatile //值可以被改变 每次必须从内存获取值 防止被编译器优化
#define __I volatile const //值不希望被改变,保持这个值为只读常量
#define __STATIC_INLINE static inline //内敛函数 适用代码短的函数
typedef struct {
union{
struct
{
__IO uint32_t IRC8MEN :1; // bit0
__I uint32_t IRC8MSTB :1; // bit1
__IO uint32_t :1; // bit2
__IO uint32_t IRC8MADJ :5; // bit[7:3]
__I uint32_t IRC8MCALIB :8; // bit[15:8]
__IO uint32_t HXTALEN :1; // bit16
__I uint32_t HXTALSTB :1; // bit17
__IO uint32_t HXTALBPS :1; // bit18
__IO uint32_t CKMEN :1; // bit19
__IO uint32_t :4; // bit[23:20]
__IO uint32_t PLLEN :1; // bit24
__I uint32_t PLLSTB :1; // bit25
__IO uint32_t :6; // bit[31:26]
}Bits;
__IO uint32_t Byte; // 复位值: 0x4444 xx83
}RCU_CTL; // 地址偏移: 0x00 控制寄存器
union{
struct
{
__IO uint32_t SCS :2;
__I uint32_t SCSS :2;
__IO uint32_t AHBPSC :4;
__IO uint32_t APB1PSC :3;
__IO uint32_t APB2PSC :3;
__IO uint32_t ADCPSC_Bit1_0:2;
__IO uint32_t PLLSEL :1;
__IO uint32_t PREDV0 :1;
__IO uint32_t PLLMF_Bit3_0 :4;
__IO uint32_t USBFSPSC :2;
__IO uint32_t CKOUT0SEL :3;
__IO uint32_t PLLMF_Bit4 :1;
__IO uint32_t ADCPSC_Bit2 :1;
__IO uint32_t :1;
__IO uint32_t PLLMF_Bit5 :1;
__IO uint32_t USBFSPSC_Bit2:1;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}RCU_CFG0; // 地址偏移: 0x04 时钟配置寄存器 0
union{
struct
{
__I uint32_t IRC40KSTBIF :1;
__I uint32_t LXTALSTBIF :1;
__I uint32_t IRC8MSTBIF :1;
__I uint32_t HXTALSTBIF :1;
__I uint32_t PLLSTBIF :1;
__IO uint32_t :2;
__I uint32_t CKMIF :1;
__IO uint32_t IRC40KSTBIE :1;
__IO uint32_t LXTALSTBIE :1;
__IO uint32_t IRC8MSTBIE :1;
__IO uint32_t HXTALSTBIE :1;
__IO uint32_t PLLSTBIE :1;
__IO uint32_t :3;
__IO uint32_t IRC40KSTBIC :1;
__IO uint32_t LXTALSTBIC :1;
__IO uint32_t IRC8MSTBIC :1;
__IO uint32_t HXTALSTBIC :1;
__IO uint32_t PLLSTBIC :1;
__IO uint32_t :2;
__IO uint32_t CKMIC :1;
__IO uint32_t :8;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}RCU_INT; // 地址偏移: 0x08 时钟中断寄存器
union{
struct
{
__IO uint32_t AFRST :1;
__IO uint32_t :1;
__IO uint32_t PARST :1;
__IO uint32_t PBRST :1;
__IO uint32_t PCRST :1;
__IO uint32_t PDRST :1;
__IO uint32_t PERST :1;
__IO uint32_t PFRST :1;
__IO uint32_t PGRST :1;
__IO uint32_t ADC0RST :1;
__IO uint32_t ADC1RST :1;
__IO uint32_t TIMER0RST :1;
__IO uint32_t SPI0RST :1;
__IO uint32_t TIMER7RST :1;
__IO uint32_t USART0RST :1;
__IO uint32_t ADC2RST :1;
__IO uint32_t :3;
__IO uint32_t TIMER8RST :1;
__IO uint32_t TIMER9RST :1;
__IO uint32_t TIMER10RST :1;
__IO uint32_t :10;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}RCU_APB2RST; // 地址偏移: 0x0C APB2 复位寄存器
union{
struct
{
__IO uint32_t TIMER1RST :1;
__IO uint32_t TIMER2RST :1;
__IO uint32_t TIMER3RST :1;
__IO uint32_t TIMER4RST :1;
__IO uint32_t TIMER5RST :1;
__IO uint32_t TIMER6RST :1;
__IO uint32_t TIMER11RST :1;
__IO uint32_t TIMER12RST :1;
__IO uint32_t TIMER13RST :1;
__IO uint32_t :2;
__IO uint32_t WWDGTRST :1;
__IO uint32_t :2;
__IO uint32_t SPI1RST :1;
__IO uint32_t SPI2RST :1;
__IO uint32_t :1;
__IO uint32_t USART1RST :1;
__IO uint32_t USART2RST :1;
__IO uint32_t UART3RST :1;
__IO uint32_t UART4RST :1;
__IO uint32_t I2C0RST :1;
__IO uint32_t I2C1RST :1;
__IO uint32_t USBDRST :1;
__IO uint32_t :1;
__IO uint32_t CAN0RST :1;
__IO uint32_t :1;
__IO uint32_t BKPIRST :1;
__IO uint32_t PMURST :1;
__IO uint32_t DACRST :1;
__IO uint32_t :2;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}RCU_APB1RST; // 地址偏移: 0x10 APB1 复位寄存器
union{
struct
{
__IO uint32_t DMA0EN :1; //DMA0 时钟开启
__IO uint32_t DMA1EN :1;
__IO uint32_t SRAMSPEN :1;
__IO uint32_t :1;
__IO uint32_t FMCSPEN :1;
__IO uint32_t :1;
__IO uint32_t CRCEN :1;
__IO uint32_t :1;
__IO uint32_t EXMCEN :1;
__IO uint32_t :3;
__IO uint32_t USBFSEN :1;
__IO uint32_t :19;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0014
}RCU_AHBEN; // 地址偏移: 0x14 位清除寄存器
union{
struct
{
__IO uint32_t AFEN :1;
__IO uint32_t :1;
__IO uint32_t PAEN :1;
__IO uint32_t PBEN :1;
__IO uint32_t PCEN :1; //时钟开启
__IO uint32_t PDEN :1;
__IO uint32_t PEEN :1;
__IO uint32_t PFEN :1;
__IO uint32_t PGEN :1;
__IO uint32_t ADC0EN :1; //ADC0 时钟开启
__IO uint32_t ADC1EN :1;
__IO uint32_t TIMER0EN :1;
__IO uint32_t SPI0EN :1;
__IO uint32_t TIMER7EN :1;
__IO uint32_t USART0EN :1;
__IO uint32_t ADC2EN :1;
__IO uint32_t :3;
__IO uint32_t TIMER8EN :1;
__IO uint32_t TIMER9EN :1;
__IO uint32_t TIMER10EN :1;
__IO uint32_t :10;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}RCU_APB2EN; // 地址偏移: 0x18 APB2 使能寄存器
union{
struct
{
__IO uint32_t TIMER1EN :1;
__IO uint32_t TIMER2EN :1;
__IO uint32_t TIMER3EN :1;
__IO uint32_t TIMER4EN :1;
__IO uint32_t TIMER5EN :1;
__IO uint32_t TIMER6EN :1;
__IO uint32_t TIMER11EN :1;
__IO uint32_t TIMER12EN :1;
__IO uint32_t TIMER13EN :1;
__IO uint32_t :2;
__IO uint32_t WWDGTEN :1;
__IO uint32_t :2;
__IO uint32_t SPI1EN :1;
__IO uint32_t SPI2EN :1;
__IO uint32_t :1;
__IO uint32_t USART1EN :1;
__IO uint32_t USART2EN :1;
__IO uint32_t UART3EN :1;
__IO uint32_t UART4EN :1;
__IO uint32_t I2C0EN :1;
__IO uint32_t I2C1EN :1;
__IO uint32_t USBDEN :1;
__IO uint32_t :1;
__IO uint32_t CAN0EN :1;
__IO uint32_t :1;
__IO uint32_t BKPIEN :1;
__IO uint32_t PMUEN :1;
__IO uint32_t DACEN :1;
__IO uint32_t :2;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}RCU_APB1EN; // 地址偏移: 0x1C APB1 使能寄存器
union{
struct
{
__IO uint32_t LXTALEN :1;
__I uint32_t LXTALSTB :1;
__IO uint32_t LXTALBPS :1;
__IO uint32_t LXTALDRI :2;
__IO uint32_t :3;
__IO uint32_t RTCSRC :2;
__IO uint32_t :5;
__IO uint32_t RTCEN :1;
__IO uint32_t BKPRST :1;
__IO uint32_t :15;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0018
}RCU_BDCTL; // 地址偏移: 0x20 备份域控制寄存器
union{
struct
{
__IO uint32_t IRC40KEN :1;
__I uint32_t IRC40KSTB :1;
__IO uint32_t :22;
__IO uint32_t RSTFC :1;
__IO uint32_t :1;
__I uint32_t EPRSTF :1;
__I uint32_t PORRSTF :1;
__I uint32_t SWRSTF :1;
__I uint32_t FWDGTRSTF :1;
__I uint32_t WWDGTRSTF :1;
__I uint32_t LPRSTF :1;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}RCU_RSTSCK; // 地址偏移: 0x24 复位源/时钟寄存器
__IO uint32_t RCU_AHBRST; // 复位值: 0x0000 0000 // 地址偏移: 0x28 AHB 复位寄存器 (互联型CL独有?)
union{
struct
{
__IO uint32_t :29;
__IO uint32_t ADCPSC_Bit3 :1;
__IO uint32_t PLLPRESEL :1;
__IO uint32_t :1;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 0000
}RCU_CFG1; // 地址偏移: 0x2C 时钟配置寄存器 1
} RCU_Type;
/* 总线映射 */
#define AHB1_BUS_BASE ((uint32_t)0x40018000U) //系统总线基地址
/* AHB1内存映射 */
#define RCU_BASE (AHB1_BUS_BASE + 0x00009000U) //4002 1000
// GD32F30x 复位和时钟单元RCU寄存器地址映射、位域映射
#define RCU ((RCU_Type *)(RCU_BASE))//寄存器的基地址=4002 1000
#endif // RCU_H
【6】ctrl_adc.c [重要]
代码有冒泡排序
#include "ctrl_adc.h"
#include "rcu.h"
#include "gd32f30x_dma_reg.h"
#include <string.h>
//========================ADC0 测电磁阀 采样电压为例
/*============================控制MCU部分==========================*/
#define CONTINUE_MODE 1 //1连续扫描转换 0单次扫描转换。 连续模式会自动循环转换
#define ADC_RSQ_CNT (uint8_t)6 //ADC规则组要转换的通道数量
uint16_t Array_RSQ_AD[ADC_RSQ_CNT] = {0x00,0x01,0x02,0x03,0x04,0x05};//DMA0 ch0存储器地址,存储adc0转换值
static double Button_SampleVoltage[BUTTON_SAMPLE_CNT];
void Adc0_Init()
{
RCU->RCU_APB2EN.Bits.PCEN = 1; //时钟开启
RCU->RCU_APB2EN.Bits.ADC0EN =1; //ADC0 时钟开启
RCU->RCU_AHBEN.Bits.DMA0EN =1; //DMA0 时钟开启
/* ADC时钟来源:APB2分频 */
/* 0001: CK_ADC = CK_APB2 / 4 , 0111: CK_ADC = CK_APB2 / 16, ADC时钟40MHz MAX*/
RCU->RCU_CFG1.Bits.ADCPSC_Bit3 = 0; //0
RCU->RCU_CFG0.Bits.ADCPSC_Bit2 =1; //1
RCU->RCU_CFG0.Bits.ADCPSC_Bit1_0 =3; //11
//ADC配置 占4个位
ADC0->ADC_CTL0.Bits.SYNCM =0; //独立模式 0000
ADC0->ADC_CTL0.Bits.SM =1; //扫描转换模式
#if (CONTINUE_MODE == 1)
ADC0->ADC_CTL1.Bits.CTN = 1; // 0:禁止连续模式,1:使能连续模式
#else
ADC0->ADC_CTL1.Bits.CTN = 0;
#endif
ADC0->ADC_CTL1.Bits.DMA = 1; // 1: DMA 请求使能
//占4个位
ADC0->ADC_RSQ0.Bits.RL = ADC_RSQ_CNT - 1; //规则组长度,0-F表示1-16个 6-1=5=0101
//各占5个位
ADC0->ADC_RSQ2.Bits.RSQ0 = ADC_CHANNEL_11; //PC1 Mag_CUR_ADC1-8_COM 0x0B=0000 1011
ADC0->ADC_RSQ2.Bits.RSQ1 = ADC_CHANNEL_12; //PC2 Mag_CUR_ADC9-16_COM 0x0C=0000 1100
ADC0->ADC_RSQ2.Bits.RSQ2 = ADC_CHANNEL_13; //PC3 Mag_CUR_ADC17-24_COM 0x0D=0000 1101
ADC0->ADC_RSQ2.Bits.RSQ3 = ADC_CHANNEL_14; //PC4 Mag_CUR_ADC25-32_COM 0x0E=0000 1110
ADC0->ADC_RSQ2.Bits.RSQ4 = ADC_CHANNEL_15; //PC5 Mag_CUR_ADC33-40_COM 0x0F=0000 1111
ADC0->ADC_RSQ2.Bits.RSQ5 = ADC_CHANNEL_10; //PC0 按键 0x0A=0000 1001
ADC0->ADC_SAMPT0.Byte = 0x00ffffff; //0000 0000 1111 1111 1111 1111 11111 1111
ADC0->ADC_SAMPT1.Byte = 0x3fffffff; // 所有通道采样时间为ADC时钟周期 * 239.5
ADC0->ADC_CTL1.Bits.ETERC = 1; // 规则组外部触发使能
ADC0->ADC_CTL1.Bits.ETSRC = 7; // 规则组外部触发选择: 111:软件触发
ADC0->ADC_CTL1.Bits.DAL = 0; // 数据对齐:最低有效位对齐 右对齐(ADC_RDATA寄存器中)
/*规则通道单次转换结束后,转换数据将被存放于ADC_RDATA寄存器中,EOC将会置1(硬件自动置位)。如果EOCIE位被置1,将产生一个中断。*/
ADC0->ADC_STAT.Bits.EOC = 0; //clear 组转换结束标志
ADC0->ADC_CTL1.Bits.ADCON = 1; // 使能
/* 须在校正前 使能后延时14个ADC时钟周期 */
//UserTimer_Reset(&time);
//while (UserTimer_Read(&time) < 1);
/* 校准复位: 软件置位, 在校准寄存器初始化后该位硬件清零 */
ADC0->ADC_CTL1.Bits.RSTCLB = 1;
while (ADC0->ADC_CTL1.Bits.RSTCLB);
/* ADC 校准 : 0:校准结束 1:校准开始 */
ADC0->ADC_CTL1.Bits.CLB = 1;
while (ADC0->ADC_CTL1.Bits.CLB);
/* DMA配置 */
DMA0->DMA_CH0CTL.Bits.CHEN = 0; //配置DMA前须关闭通道
DMA0->DMA_CH0CTL.Bits.M2M = 0; //0: 禁止存储器到存储器模式
DMA0->DMA_CH0CTL.Bits.DIR = 0; //0:从外设读出并写入存储器
DMA0->DMA_CH0CTL.Bits.CMEN = 1; //1: 使能循环模式
DMA0->DMA_CH0CTL.Bits.PRIO = 2; //软件优先级 10: 高
DMA0->DMA_CH0CTL.Bits.MNAGA = 1; //存储器的地址生成算法 1: 增量地址模式
DMA0->DMA_CH0CTL.Bits.PNAGA = 0; //外设的地址生成算法 0: 固定地址模式
DMA0->DMA_CH0CTL.Bits.MWIDTH = 1; //存储器的传输数据宽度 01: 16-bit
DMA0->DMA_CH0CTL.Bits.PWIDTH = 1; //外设的传输数据宽度 01: 16-bit
DMA0->DMA_CH0PADDR = (uint32_t)(&ADC0->ADC_RDATA); //ADC0规则数据寄存器地址
#if (CONTINUE_MODE == 1)
DMA0->DMA_CH0MADDR = (uint32_t)(&Array_RSQ_AD); //ADC0规则数据存放基地址
DMA0->DMA_CH0CNT.Bits.CNT = ADC_RSQ_CNT; //x个数据等待被传输
DMA0->DMA_CH0CTL.Bits.CHEN = 1; //1:使能该通道
#else
#endif
#if (CONTINUE_MODE == 1)
ADC0->ADC_CTL1.Bits.SWRCST = 1; // 规则组转换开始
#else
#endif
}
// 获取AD转换结果
void Adc0_GetRSQVal(uint16_t *array, uint8_t offset, uint8_t len)
{
if ((offset < ADC_RSQ_CNT) && ((offset + len) <= ADC_RSQ_CNT))
{
//从 Array_RSQ_AD+offset 拷贝len*2个长度数据给array
memcpy(array, Array_RSQ_AD+offset, len*2); //内存拷贝 len*2 >2*unsigned char = unsigned short
}
}
/**
* @brief 配置并开始组转换
* @note 每次扫描5个通道
* @param x = 0 - 7
*/
void Adc0_GroupScan(void)
{
#if (CONTINUE_MODE == 0)
static uint8_t convert = 1;
if (convert == 1)
{
DMA0->DMA_CH0CTL.Bits.CHEN = 0; //配置DMA前须关闭通道
DMA0->DMA_CH0MADDR = (uint32_t)(&Array_RSQ_AD); //ADC0规则数据存放基地址
DMA0->DMA_CH0CNT.Bits.CNT = 5; //x个数据等待被传输
DMA0->DMA_CH0CTL.Bits.CHEN = 1; //1:使能该通道
ADC0->ADC_CTL1.Bits.SWRCST = 1; // 规则组转换开始
convert = 0; //转换中
}
else
{
if (Adc0_GroupScan_IsOK() == true)
{
convert = 1; //转换完成
}
}
#endif
}
//main 函数调用
void RB_ADC_Init()
{
/* ADC0 */
Adc0_Init();
}
//main 函数调用
void RB_ADC_ScanButton()
{
uint16_t AD[1] = {0};//ADC0转化结果zhi
static uint8_t SampleCnt = 0; //本函数的调用次数
uint16_t Voltage = 0;//电压中间值
if(SampleCnt == 11)
return;
Adc0_GetRSQVal(AD, 5, 1);//获取AD值 偏移5 长度1 每次获取最后一个值
Button_SampleVoltage[SampleCnt++] = 3300.0 * AD[0] / 4096;
printf("AD =0x0%x \n",AD[0]);
printf("AD VCC+ = %.2lf \n",Button_SampleVoltage[0]);
if (SampleCnt >= BUTTON_SAMPLE_CNT) //完成一组采样
{
Fun_BubbleSort(Button_SampleVoltage, BUTTON_SAMPLE_CNT, 1); //从小到大排序
for(int i =0;i<BUTTON_SAMPLE_CNT;i++)
{
printf("AD VCC+ = %.2lf \n",Button_SampleVoltage[i]);
}
Voltage = Button_SampleVoltage[BUTTON_SAMPLE_CNT / 2]; //取中间值
printf("need VCC = %hd\n",Voltage);
}
}
//冒泡排序
void Fun_BubbleSort(uint16_t *array, uint8_t len, uint8_t sort_dir)
{
uint8_t i = 0;
uint8_t j = 0;
uint16_t temp = 0;
for (i = 0; i < len-1; i++) //有len个数则需要比较len-1轮, 8个数比较7轮后就剩下一个数,不需比较
{
for (j = 0; j < len-i-1; j++) //i:每完成1轮,就多1个不参与下轮比较,第一轮比较完成后最右边的值即为该数组的最大值
{ //1
if ((sort_dir == 0 && array[j] < array[j + 1]) //从大到小的顺序,且前一个数小于后一个
|| (sort_dir == 1 && array[j] > array[j + 1]))//从小到大的顺序,且前一个数大于后一个
{
temp = array[j];
array[j] = array[j + 1]; //交换
array[j + 1] = temp;
}
}
}
}
static uint16_t Valve_Adc_Value[40] = {0}; //存放电磁阀AD采样结果
//main 函数调用 获取ADC的值 从0开始获取5个
void RB_ADC_ScanButton2()
{
uint16_t adcVal[5] = {0};//获取5个ad值
static uint8_t CD4051_Chx = 0; //cd4051通道x
const uint8_t ch0[5] = {V303 - 1, V401 - 1, V307 - 1, V405 - 1, V409 - 1}; //当5片CD4051都选择通道0时,adVal[0-4]的值对应V303, V401......
static int adcont=0;
if(CD4051_Chx == 8)return;
Adc0_GetRSQVal(adcVal, 0, 5);//获取ad的值
printf("AD val =%hd \n",adcVal[adcont++]);
for (int i = 0; i < 5; i++)
{
Valve_Adc_Value[ch0[i]] = adcVal[i];
printf("Valve_Adc_Value VCC = %hd\n",Valve_Adc_Value[ch0[i]]);
}
//函数调用次数=5次不在调用
if (++CD4051_Chx >= 5) CD4051_Chx = 8;
}
【7】mon_adc.c [参考+1]
#include "mon_adc.h"
//初始化测试用
void InitTest()
{
printf("ADC = %p\r\n",ADC);
printf("ADC_ANA_CHANNEL = %p\r\n",ADC_ANA_CHANNEL);
printf("ADC_AUXADC_CFG0 = %p\r\n",ADC_AUXADC_CFG0);
printf("ADC_MCU_ADCBUF_CFG0 = %p\r\n",ADC_MCU_ADCBUF_CFG0);
// uint8_t flag =0;
// while(!flag); // 真 原地踏步
printf("Next\n");
struct node {
union{
struct
{
__IO uint32_t WDE :1;
__IO uint32_t EOC :1;
__IO uint32_t EOIC :1;
__IO uint32_t STIC :1;
__IO uint32_t STRC :1;
__IO uint32_t :27;
}Bits;
__IO uint32_t Byte; // 复位值: 0x0000 C000
}ADC_STAT; // 地址偏移: 0x00 状态寄存器
};
struct node node_t;
node_t.ADC_STAT.Byte=0x11111111;
printf("%x \t",node_t.ADC_STAT.Bits.WDE);
printf("%x \t",node_t.ADC_STAT.Bits.EOC);
printf("%x \t",node_t.ADC_STAT.Bits.EOIC);
printf("%x \t",node_t.ADC_STAT.Bits.STIC);
printf("%x \t",node_t.ADC_STAT.Bits.STRC);
printf("%x \t",node_t.ADC_STAT.Byte);
}
/*============================监控MCU部分==========================*/
//DAM 直接存储访问 初始化暂不使用
void ADC_DMAInit()
{
/* ****** 配置ADC模块寄存器,使能ADC DMA功能 ****** */
ADC->CTRL1 |= ADC_CTRL1_DMAEN_Msk ;
}
//初始化多通道的ADC采集
void ADC_Init()
{
ADC_InitType ADCconfig={0};
ADC_TrigSourceType ADCtrigsrc={0};
//ADC引脚配置
//ADC 参数配置
ADCconfig.dataAlign = ADC_DataAlign_Right; //数据右对其
ADCconfig.scanMode = ADC_Regular_Single_One_Mode;//一次只转换一个通道,mode1
//ADC 参数初始化 start
uint32_t tmp =0;
//外设时钟使能控制
*(volatile unsigned int *)(PERI_CLK_EN_1) |= (uint32_t)(1<<(uint32_t)(CLK_ADC-32));
//外设软件复位
*(volatile unsigned int *)(PERI_SFT_RST2) |= (uint32_t)(1<<(uint32_t)(SRST_ADC-32));
//ADC模式选择
tmp = ADC->CTRL1;//CTRL1寄存器的11~15位为 Mode 选择
tmp &= ADC_MODE_RESET;//ADC 转换模式复位
tmp |= ((uint32_t)(ADCconfig.injectAutoMode
| ((uint32_t)ADCconfig.disContinousModeOnInjectGroup << 1)\
| ((uint32_t)ADCconfig.disContinousModeOnRegularGroup << 2)\
| ((uint32_t)ADCconfig.continousMode << 3)\
| ((uint32_t)ADCconfig.scanMode << 4))) << 11;
ADC->CTRL1 = tmp; //或运算 同时具备这些项的功能
//ADC 数据的对齐方式
ADC->CTRL1 = (ADC->CTRL1 & ~(ADC_CTRL1_ALIGN_Msk)) | ((((uint32_t)(((uint32_t)(ADCconfig.dataAlign))<<ADC_CTRL1_ALIGN_Pos))&ADC_CTRL1_ALIGN_Msk));
//ADC 不连续的转换长度配置
ADC->CTRL1 = (ADC->CTRL1 & ~(ADC_CTRL1_DISCNUM_Msk)) | (((uint32_t)(((uint32_t)(ADCconfig.discNum))<<ADC_CTRL1_DISCNUM_Pos))&ADC_CTRL1_DISCNUM_Msk);
//两个结构体的位清空
ADC_AUXADC_CFG0->ADC_RSV1 &=~ ADC_AUXADC_CFG0_RSRV1_Msk;
ADC_MCU_ADCBUF_CFG0->ADCBUF_RSV1 &=~ ADC_MCU_ADCBUF_CFG0_RSRV1_Msk;
ADC_AUXADC_CFG0->ADC_RSV1 &=~ ADC_AUXADC_CFG0_RSRV0_Msk;
ADC_MCU_ADCBUF_CFG0->ADCBUF_RSV1 &=~ ADC_MCU_ADCBUF_CFG0_RSRV0_Msk;
//ADC 参数初始化 end
//ADC 规则组 触发源设置
ADCtrigsrc.regularTrigSource = ADC_TrigSource_Internal;//软件触发;规则组 选择内部触发
ADC->CTRL1 &=TRIG_SOURCE_SETTING_RESET;//转换触发源复位
ADC->CTRL1 = (ADC->CTRL1 & ~(ADC_CTRL1_EXTTRIG_Msk)) | (((uint32_t)(((uint32_t)(ADCtrigsrc.regularTrigSource))<<ADC_CTRL1_EXTTRIG_Pos))&ADC_CTRL1_EXTTRIG_Msk);
ADC->CTRL1 = (ADC->CTRL1 & ~(ADC_CTRL1_IEXTTRIG_Msk))|(((uint32_t)(((uint32_t)(ADCtrigsrc.injectTrigSource))<<ADC_CTRL1_IEXTTRIG_Pos))&ADC_CTRL1_IEXTTRIG_Msk);
/* ****** 设置分频系数,48M/8=6Mhz ****** */
ADC->CTRL2 = (ADC->CTRL2 & ~(ADC_CTRL2_PSC_Msk)) |(((uint32_t)(((uint32_t)(ADC_ADIV_DIVIDE_8))<<ADC_CTRL2_PSC_Pos))&ADC_CTRL2_PSC_Msk);
/* ****** 规则组,通道总数只有1个 ****** */
uint32_t length=1;
ADC->RSQR1 = (ADC->RSQR1 & ~(ADC_RSQR1_RSQL_Msk))|(((uint32_t)(((uint32_t)(length-1))<<ADC_RSQR1_RSQL_Pos))&ADC_RSQR1_RSQL_Msk);
/* ****** ADC 使能 ****** */
ADC->CTRL2 |=ADC_CTRL2_ADON_Msk;
}
//复位ADCx外设
void ADC_Deinit()
{
//外设时钟控制失能
*(volatile unsigned int *)(PERI_CLK_EN_1) &= ~((uint32_t)(1<< (uint32_t)(CLK_ADC-32)));
//外设软件复位失效
*(volatile unsigned int *)(PERI_SFT_RST2) &= ~((uint32_t)(1<< (SRST_ADC-32)));
printf("ADC_Deinit\r\n");
}
//获取指定ADC通道值
uint32_t GetAdcChannelValue(uint32_t Channel)
{
/* ****** 选择转换通道 ****** */
uint32_t seq=0;
if(Channel ==0 || Channel ==1 || Channel ==2 || Channel ==8 ||Channel==11 || Channel==12 )
{
seq =1;
}
if(seq <7)//ADC 规则组序列配置寄存器3
{
ADC->RSQR3 &=~((0x1FUL)<<((seq-1)*5));
ADC->RSQR3 |= ((Channel)<<((seq-1)*5));
}
else if(seq <13)//ADC 规则组序列配置寄存器2
{
ADC->RSQR2 &=~((0x1FUL)<<((seq-7)*5));
ADC->RSQR2 |= ((Channel)<<((seq-7)*5));
}
else //>=13 ADC 规则组序列配置寄存器1
{
ADC->RSQR2 &=~((0x1FUL)<<((seq-13)*5));
ADC->RSQR2 |= ((Channel)<<((seq-13)*5));
}
//ADC 通道状态寄存器
ADC_ANA_CHANNEL->MODE &=~ (0x01UL<<(31-Channel));
/* ****** 设置通道采样时间 ****** */
if (Channel < 10)//ADC 采样时间设置寄存器2
{
ADC->SPT2 &= ~(0x7UL << ((Channel) * 3));
ADC->SPT2 |= (ADC_SampleTime_14Cycle << ((ADC_SampleTime_14Cycle) * 3));
}
else//ADC 采样时间设置寄存器1
{
ADC->SPT1 &= ~(0x7UL << ((Channel - 10) * 3));
ADC->SPT1 |= (ADC_SampleTime_14Cycle << ((Channel - 10) * 3));
}
/* ****** 软件触发转换 ****** */
ADC->CTRL1 |= ADC_CTRL1_SWSTART_Msk;
while(!(ADC->STR & ADC_FLAG_EOC));//等待转换完成 即有值的时候就退出循环
return ((uint16_t)ADC->RDR);//返回转换结果 ADC规则组数据寄存器
}
//ADC 中断服务程序
void ADC_IRQHandler()
{
if (g_adcCallback[0])
{
g_adcCallback[0]();
printf("fun start callback\r\n");
}
printf("fun ptr NULL\r\n");
}
【8】main.c [参考+2]
//#include "mon_adc.h"
#include "ctrl_adc.h"
/*项目总入口*/
int main()
{
//# if defined (F1)
#if (0)
FILE *fd;
const char *p ="123456789"; //['1''2''3''4''5''6''7''8'9']="123456789"
fd = fopen("C://Users//sujieyin//Desktop//QT//MCU//1.txt","w");//只写方式打开 不存在就创建
printf("%d ",strlen(p));//字符串实际长度
for (uint_fast32_t i=0;i<strlen(p);i++) {
int ret = fputc(p[i],fd);//传入的整数被当作ASCII字符
printf("ret =%d \n",ret);//返回ASCII码的10进制
}
fclose(fd);
#endif
#if 0
char buf[16]={0};//正确形式
//char buf[16];//不初始化 里面存有随机值
printf("sizeof =%d \n",sizeof (buf));
printf("strlen =%d \n",strlen(buf));
for (int i=0;i<strlen(buf);i++) {
printf("i =%d \n",buf[i]);
}
/* 输出结果
* sizeof =16
strlen =3
i =-5
i =23
i =64
*/
int ret =snprintf(buf,sizeof (buf),"%s","12345678901234567890");
printf("ret size =%d \n",ret);
printf("buf =%s \n",buf);
/* 显然给buf的字符串长度不能超出buf的大小 否侧出现写入不全
sizeof =16
strlen =0
ret size =-1
buf =1234567890123456
*/
#endif
/*==========================控制MCU调用ADC实例=======================*/
/*医疗设备 电磁阀的控制和监控 初始化*/
printf("\r\n ADC0 init ok \r\n");
//RB_ADC_Init();
while(2022)
{
/* 屏幕下方物理按键 */
RB_ADC_ScanButton();
/*监控电磁阀实际动作和配置是否相符*/
RB_ADC_ScanButton2();
}
return 0;
}