外观
ADC输入实验
电路分析
数控直流电源的电压检测 电流检测本质上都是通过读取ADC值从而转换电压值实现的,在实际的工程代码中,注意是需要将ADC值进行换算、滤波,从而获取一个相对准确的电压值。
功能实现
创建工程
- 打开cubemx软件,配置工程;在此之前需要确保你已经成功安装stm32cubemx软件以及keil软件并下载好对应的芯片支持包了。
注
固态继电器相关引脚默认要拉高,这是为了默认关断固态继电器,同时有一点,切勿把三个引脚都同时拉低,在同一时刻只能有一个固态继电器打开,否则高电压会影响低电压,这一点在配置以及后续代码编写过程中都非常重要。
ch224是电源诱骗芯片,我们可以通过控制对应的引脚来控制输出电压,配置的电平需参考数据手册,默认cfg为1输出5V电平比较合适。
机械按键在按下与松开时,不可避免会产生机械抖动,在进行按键判断时,需要进行消抖操作减少抖动的影响,抖动时间通常是10~30ms之间,最简单的消抖操作是通过延时死等的方式去除抖动。
代码实现
默认生成的代码编译是没有任何问题的,若有问题,基本上就是环境文件,需要重新检查安装,建议把错误信息复制到百度进行查找解决。
在gpio.c中编写或拷贝之前几节课的代码,oled显示部分复制上一个实验的库文件过来,然后重新添加路径即可,剩余adc部分的代码在adc.c文件中进行编写,adc部分的初始化代码系统都已经默认生成好了,后续仅需要编写读取adc值的代码并做转换即可。
准备工作完成后,在main函数中进行逻辑代码的编写,这里需要先经过oled屏幕的初始化以及adc的内部校准(也可以不用),在循环中,进行按键扫描以及数据显示,这里adc读取的值是扫描顺序读取,第一次读取是AIN0的值,也就是电流通道,第二次读取的AIN5的值,也就是电压通道,读取的值是12的ADC值(0~4095),不是一个模拟电压,这里需要将读取的adc值换算为电压值,具体公式也比较简单(ADC值*实际电压值)/4095即可,注意实际电压值可能不是3.3V,需要自己测量;电流的换算就还需要多一步,详细描述在电路分析章节。
主函数代码
C
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t keyValue = 0;
uint32_t tempValue = 0;
float tempCurValue = 0,tempVolValue = 0;
char showData[32] = {0};
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
HAL_ADCEx_Calibration_Start(&hadc);
OLED_Init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
keyValue = keyScanf();
keyHandler(keyValue);
tempValue = getAdcValue();
tempCurValue = (tempValue * 3.36f)/4095.0f;
tempCurValue = (tempCurValue / 100.0f / 0.01f * 1000);
tempValue = getAdcValue();
tempVolValue = (tempValue * 3.36f)/4095.0f;
tempVolValue = (13.3f * tempVolValue)/3.3f;
HAL_ADC_Stop(&hadc);
sprintf(showData,"Vol:%.1f",tempVolValue);
OLED_ShowString(0,0,(uint8_t *)showData,16,1);
sprintf(showData,"Cur:%.1f",tempCurValue);
OLED_ShowString(0,16,(uint8_t *)showData,16,1);
OLED_Refresh();
}
/* USER CODE END 3 */
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
注
当代码烧录进去后,默认是关闭的,此时电压值显示0,当按下设置按键时,3.3V继电器打开,电压值显示3.3V左右,这里读取的值,以及刷新的数据都非常快,在while循环中没有任何延时等待,但是实际上电压的变化通常是不会很大的,很多时候这里都在做无用的刷新。大家可以自行优化代码,注意考虑按键扫描对时序的要求,为最后的综合代码做准备。
一定注意不可同时打开多个继电器,这里再三强调。
若发现输出9V、12V失败,可以看看自己的充电头或充电线是不是不支持该电压输出。