谢谢 B 站的"水手勇敢"博主,带着咱们改写了江科大的标准库程序,改用 HAL 库实现,保持了学习的连贯性(107)
++这里做少量记录。

++

++

++

++

++

++

++

(108)main.c 文件里,调用了这几个函数, 但这几个函数,定义在 OLED.c 源文件里,而且 main.c 并没有包含 OLED.c 对应的头文件,而且编译也不报错,这是为啥,这还是 C 语言么?

++ 以下是 dou 包的回答 :




++ 测试, dou 包是正确的,确实出现了大量关于函数调用的警告 :

++

(109)ADC 的单次范围转换 :
++ 在标准库中, 单次的范围转换,包含多个序列 rank,对应多个 channel, 全部转换完成才会停止,导致数据覆盖。妥协的实现办法,不用 DMA,就是只用一个序列 髯口, 为其配置不同的通道,从而也能实现范围 scan 转换的效果。 但在 HAL CUBE 里,由于配置参数的变化,如下 :

++ dou 包的解释 :


++ 以下的代码的正确执行,就依赖于 CUbe 里的这个 discontinue 机制,标准库里没有这个 :
c
uint16_t values[4] = {0}; //用于存放ADC数据
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
/*模块初始化*/
OLED_Init(); //OLED初始化
HAL_ADCEx_Calibration_Start(&hadc1); //使用前校准
OLED_Clear();
OLED_ShowString(1, 1, "v1:");
OLED_ShowString(2, 1, "v2:");
OLED_ShowString(3, 1, "v3:");
OLED_ShowString(4, 1, "v4:");
while (1)
{
for(uint8_t i = 0; i<4; i++)
{
HAL_ADC_Start(&hadc1); //ADC启动,开始转换
if(HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY) == HAL_OK)
{
values[i] = HAL_ADC_GetValue(&hadc1);
}
}
OLED_ShowNum(1, 5, values[0], 4);
OLED_ShowNum(2, 5, values[1], 4);
OLED_ShowNum(3, 5, values[2], 4);
OLED_ShowNum(4, 5, values[3], 4);
HAL_Delay(1000);
}
++ 当然,这种情况下,最正确的做法是 DMA。
(110)

++ HAL 库里的结构体封装,好深啊 :
c
//启动循环模式
hdma_memtomem_dma1_channel1.Init.Mode = DMA_CIRCULAR; // 循环 DMA
HAL_DMA_Init(&hdma_memtomem_dma1_channel1);
//启动DMA
HAL_DMA_Start(&hdma_memtomem_dma1_channel1,(uint32_t*)&DataA,(uint32_t*)&DataB,4);
while (1)
{
for(uint16_t i=0;i<4;i++)
{
DataA[i]++;
}
for(uint16_t i=0;i<4;i++)
{
OLED_ShowHexNum(1, 1+3*i, DataA[i], 2);
}
for(uint16_t j=0;j<4;j++)
{
OLED_ShowHexNum(3, 1+3*j, DataB[j], 2);
}
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
(111)
谢谢