1. 程式人生 > >STM32CubeMX學習教程之八:DAC輸出電壓,ADC讀取電壓並輸出到串列埠

STM32CubeMX學習教程之八:DAC輸出電壓,ADC讀取電壓並輸出到串列埠

完整原始碼下載:https://github.com/simonliu009/STM32CubeMX-DAC-and-ADC

這一篇教程目標是由DAC輸出一個階梯電壓,把它連線到一個ADC,由ADC讀取這個電壓並輸出到串列埠。

軟體:

STM32CubeMX V4.25.0  

System Workbench V2.4

韌體庫版本:
STM32Cube FW_F1 V1.6.1

硬體:

OneNet 麒麟座V2.3

首先用一條杜邦線短接PA4和PA6兩個引腳。我們會把PA4配置為DAC,PA6配置為ADC。

在STM32CubeMX中新建專案,選擇正確的MCU型號


首先設定RCC和SYS,如下圖

配置USART1為Asychronous模式

UART1配置用預設的115200,8, None和1就好。


然後設定PA4為DAC_OUT1, PA6引腳為ADC2_IN6, 完整引腳配置如下圖:


然後根據板子實際情況設定時鐘(麒麟座外部晶振是12M,STM32F103x的最高主頻是72M),注意CubeMX可能會自動把ADC預分頻係數設為6。


DAC和ADC設定都使用預設設定

Project - setting ,ToolChain/IDE選擇 SW4STM32


勾選這裡


儲存以後,點選工作列的生成程式碼圖示


生成完畢以後在彈出的對話方塊點選"Open Project", System Workbench自動開啟Eclipse並匯入和打開了專案。

參考前面文章的printf()重定向到串列埠的程式碼,編輯main.c, 新增如下程式碼


  1. /* Private function prototypes -----------------------------------------------*/
  2. #ifdef __GNUC__
  3. /* With GCC, small printf (option LD Linker->Libraries->Small printf 
  4.    set to 'Yes') calls __io_putchar() */
  5. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
  6. #else
  7. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
  8. #endif /* __GNUC__ */
  9. /* Private functions -------------------------------------------------  
  1. /* USER CODE BEGIN 0 */
  2. PUTCHAR_PROTOTYPE  
  3. {  
  4.     HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);  
  5.     return ch;  
  6. }  
  7. /* USER CODE END 0 */

然後修改main.c,新增兩個變數儲存DAC和ADC的值

  1. /* USER CODE BEGIN 1 */
  2. int16_t DAC_Value; 
  3. int16_t ADC2_Value;  
  4. /* USER CODE END 1 */

輸出內容:

/* USER CODE BEGIN 3 */
	  if (DAC_Value >= 3967)
	  {
		  DAC_Value = 0;
	  }
	  DAC_Value += 128;
	  printf("DAC Value : %d \r\n",DAC_Value);
	  HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, DAC_Value);
      HAL_Delay(500);
      HAL_ADC_Start(&hadc2);
      HAL_ADC_PollForConversion(&hadc2, 50);

      if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc2), HAL_ADC_STATE_REG_EOC))
      {
          ADC2_Value = HAL_ADC_GetValue(&hadc2);
          printf("ADC2 Reading : %d \r\n",ADC2_Value);
          printf("PA6 Voltage : %.4f \r\n",ADC2_Value*3.3f/4096);
          printf("\r\n");
      }

      HAL_Delay(2000);
  }
  /* USER CODE END 3 */

注意這裡printf()輸出浮點數%.4f會提示錯誤: 

The float formatting support (-u _printf_float) is not enabled from linker flags

所以需要在這裡新增一個-u _printf_float

project properties > C/C++ Build > Settings > Tool Settings (TAB) > MCU GCC Linker > Miscellaneous > Linker flags

把-specs=nosys.specs -specs=nano.specs 改為 -specs=nosys.specs -specs=nano.specs -u _printf_float

最後,不要忘記把STM32Cube_FW_F1_V1.6.0\Projects\STM3210C_EVAL\Examples\UART\UART_Printf\syscalls.c 檔案複製到src目錄,很多教程沒有提到這點。如果不復制這個檔案,那麼printf()是不起作用的。

然後右鍵點選專案,選擇Properties, Run-Debug Settings, 點選右側的New,在彈出對話方塊中選擇Ac6 STM32 Debugging。


然後工作列上點選Run圖,當然會報錯的,原因請檢視另一篇我的部落格(https://blog.csdn.net/toopoo/article/details/79680323),所以需要右鍵點選  專案名Run.cfg ,給它改個名字,


然後右鍵點選專案樹裡面的專案名稱,選擇“Propeties”,然後在Run/Debug Settings-選擇專案名-Edit-Main-C/C++Application那裡點選“Search Project”,然後選擇出現的預設的elf檔案:


然後在Debugger-User Defined-Browse 那裡選擇你自己改名的配置檔案:


然後右鍵點選那個新的cfg檔案,選擇"Open With - Text Editor", 進行如下更改:

source [find interface/stlink.cfg] 更改為 source [find interface/stlink-v2.cfg]

reset_config srst_only srst_nogate connect_assert_srst 這一行改為 reset_config none 

然後再Run一下,就可以了。


然後使用串列埠程式,波特率設為115200,就可以看到如下這些資訊:


DAC Value : 128 
ADC2 Reading : 66 
PA6 Voltage : 0.0532 

DAC Value : 256 
ADC2 Reading : 193 
PA6 Voltage : 0.1555 

DAC Value : 384 
ADC2 Reading : 321 
PA6 Voltage : 0.2586 

DAC Value : 512 
ADC2 Reading : 448 
PA6 Voltage : 0.3609 

DAC Value : 640 
ADC2 Reading : 576 
PA6 Voltage : 0.4641 

DAC Value : 768 
ADC2 Reading : 704 
PA6 Voltage : 0.5672 

DAC Value : 896 
ADC2 Reading : 832 
PA6 Voltage : 0.6703 

DAC Value : 1024 
ADC2 Reading : 1140 
PA6 Voltage : 0.9185 

DAC Value : 1152 
ADC2 Reading : 1089 
PA6 Voltage : 0.8774 

DAC Value為1152時,麒麟座的蜂鳴器開始鳴叫,因為PA4引腳是蜂鳴器的使能引腳,0.8V已經能讓蜂鳴器工作了。

DAC和ADC讀數有差距是因為線材的壓降和噪聲的影響。