プロジェクト:
https://github.com/ryood/STM32Cube_Test/tree/master/SW4STM32/Nucleo-F446_MCP3028_Test1
実行環境
- Nucleo-F446RE
- STM32CubeMX Version 5.1.0
- System Workbench for STM32 - C/C++ Embedded Development Tools for MCU Version: 2.8.1.201903050911
配線
STM32CubeMXの設定
CLOCK Confiiguration
[HCLK]: 128
プリスケーラ-で分周しやすいようにHCLKを128MHz。
[SPI1]-[Parameter Settings]
Clock Prameters
Prescaler(for Baud Rate): 64
MCP3208はVdd=2.7Vのときクロック周波数は最大1.0MHzなのでそれに合わせてプリスケーラ-を設定。
GPIOの設定
SPI1のNSS(CS)をソフトウェア制御するために、GPIOで[SPI1_CS]を割り当て。
SW4STM32でコードを追加(一部抜粋)
/* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ #define MCP3208_START_BIT 0x04 #define MCP3208_MODE_SINGLE 0x02 // Single-ended mode #define MCP3208_MODE_DIFF 0x00 // Differential mode /* USER CODE END PD */
/* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ #ifdef __GNUC__ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif PUTCHAR_PROTOTYPE { HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF); return ch; } uint16_t MCP3208_read_u16(uint8_t channel) { uint8_t aTxBuffer[3]; uint8_t aRxBuffer[3]; aTxBuffer[0] = MCP3208_START_BIT | MCP3208_MODE_SINGLE | ((channel & 0x04) >> 2); aTxBuffer[1] = (channel & 0x03) << 6; aTxBuffer[2] = 0; HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET); if(HAL_SPI_TransmitReceive(&hspi1, aTxBuffer, aRxBuffer, 3, 100) != HAL_OK) { /* Transfer error in transmission process */ Error_Handler(); } HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET); // RXデータの2バイト目の上位4ビットは値が不定のため0x0fでマスキング uint16_t conv_result = ((uint16_t)(aRxBuffer[1] & 0x0f) << 8) | (uint16_t)aRxBuffer[2]; return conv_result; } /* USER CODE END 0 */
MCP3208のデータシートを見ると、SPIで8bit単位で送受信すると、RXデータ(12bit)の上位3ビットはHI-Zで不定になり、4ビット目は0になるようです。このためRXデータ(aRxBuffer[])の2バイト目の上位4ビットはプログラムで読み捨てています。
↑DOUTがNucleo-F446側から見るとRXデータになります。
/* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ uint16_t adcv[3] = {0}; for (int i = 0; i < 3; i++) { adcv[i] = MCP3208_read_u16(i); } printf("Read VAL:\t%d\t%d\t%d\r\n", adcv[0], adcv[1], adcv[2]); } /* USER CODE END 3 */
メインループでMCP3208をポーリングして、値をprintf(UART出力)しています。
SPI信号波形
MISO
ch1:MISO ch2:SCK
MOSI
ch1:MOSI ch2:SCK
<追記:2019.03.29>
MOSIの3バイト目(aTxBuffer[2])は「0」のハズなのに、値が出力されてますね(@@? バグがありそうです。
</追記>
CS
ch1:CS ch2:SCK
Puttyで受信しているようす
メモ
3連POTのch0(黄色)が動作不良。
0 件のコメント:
コメントを投稿