How to use Digital-to-Analog Converter (DAC) with STM32F10C8 Board
Chúng ta đều biết rằng Bộ vi điều khiển chỉ hoạt động với các giá trị kỹ thuật số nhưng trong thế giới thực, chúng ta phải xử lý các tín hiệu tương tự. Đó là lý do tại sao ADC (Bộ chuyển đổi tương tự sang kỹ thuật số) ở đó để chuyển đổi các giá trị Analog trong thế giới thực thành dạng Kỹ thuật số để bộ vi điều khiển có thể xử lý tín hiệu. Nhưng điều gì sẽ xảy ra nếu chúng ta cần tín hiệu Analog từ các giá trị kỹ thuật số, vì vậy ở đây có DAC (Digital to Analog Converter).
Một ví dụ đơn giản cho bộ chuyển đổi Digital sang Analog là ghi một bài hát trong phòng thu nơi ca sĩ nghệ sĩ đang sử dụng micrô và hát một bài hát. Các sóng âm thanh tương tự này được chuyển đổi thành dạng kỹ thuật số và sau đó được lưu trữ trong tệp định dạng kỹ thuật số và khi bài hát được phát bằng tệp kỹ thuật số được lưu trữ, các giá trị kỹ thuật số đó sẽ được chuyển đổi thành tín hiệu tương tự cho đầu ra loa. Vì vậy, trong hệ thống này DAC được sử dụng.
DAC có thể được sử dụng trong nhiều ứng dụng như điều khiển động cơ, điều khiển độ sáng đèn LED, bộ khuếch đại âm thanh, bộ mã hóa video, hệ thống thu thập dữ liệu, v.v.
Chúng tôi đã giao tiếp Mô-đun DAC MCP4725 với Arduino. Hôm nay chúng ta sẽ sử dụng cùng một IC DAC MCP4725 để thiết kế một bộ chuyển đổi Digital sang Analog sử dụng Vi điều khiển STM32F103C8.
Components Required
- STM32F103C8
- MCP4725 DAC IC
- 10k Potentiometer
- 16x2 LCD display
- Breadboard
- Connecting Wires
MCP4725 DAC Module (Digital to Analog Converter)
Formula to calculate Output Voltage
O/P Voltage = (Reference Voltage / Resolution) x Digital Value
For Example if we use 5V as reference voltage and let’s assume that digital value is 2048. So to calculate the DAC output.
O/P Voltage = (5/ 4096) x 2048 = 2.5V
Below is the image of MCP4725 with clearly indicating pin names.
Pins of MCP4725 | Use |
OUT | Outputs Analog Voltage |
GND | GND for Output |
SCL | I2C Serial Clock line |
SDA | I2C Serial Data line |
VCC | Input Reference Voltage 5V or 3.3V |
GND | GND for input |
I2C Communication in MCP4725
IC DAC này có thể được giao tiếp với bất kỳ vi điều khiển nào bằng giao tiếp I2C. Giao tiếp I2C chỉ cần hai dây SCL và SDA. Theo mặc định, địa chỉ I2C cho MCP4725 là 0x60. Theo liên kết để biết thêm về giao tiếp I2C trong STM32F103C8.
I2C pins in STM32F103C8:
SDA: PB7 or PB9, PB11.
SCL: PB6 or PB8, PB10.
Circuit Diagram and Explanation
Connections between STM32F103C8 & 16x2 LCD
LCD Pin No | LCD Pin Name | STM32 Pin Name |
1 | Ground (Gnd) | Ground (G) |
2 | VCC | 5V |
3 | VEE | Pin from Centre of Potentiometer for contrast |
4 | Register Select (RS) | PB11 |
5 | Read/Write (RW) | Ground (G) |
6 | Enable (EN) | PB10 |
7 | Data Bit 0 (DB0) | No Connection (NC) |
8 | Data Bit 1 (DB1) | No Connection (NC) |
9 | Data Bit 2 (DB2) | No Connection (NC) |
10 | Data Bit 3 (DB3) | No Connection (NC) |
11 | Data Bit 4 (DB4) | PB0 |
12 | Data Bit 5 (DB5) | PB1 |
13 | Data Bit 6 (DB6) | PC13 |
14 | Data Bit 7 (DB7) | PC14 |
15 | LED Positive | 5V |
16 | LED Negative | Ground (G) |
Connection between MCP4725 DAC IC and STM32F103C8
MCP4725 | STM32F103C8 | Multimeter |
SDA | PB7 | NC |
SCL | PB6 | NC |
OUT | PA1 | Positive Probe |
GND | GND | Negative Probe |
VCC | 3.3V | NC |
Một chiết áp cũng được kết nối, với chân giữa được kết nối với đầu vào tương tự PA1 (ADC) của STM32F10C8, Chân trái kết nối với GND và chân phải nhất kết nối với 3.3V của STM32F103C8.
Trong hướng dẫn này, chúng tôi sẽ kết nối một IC DAC MCP4725 với STM32 và sử dụng một chiết áp 10k để cung cấp giá trị đầu vào tương tự cho chân STM32 ADC PA0. Và sau đó sử dụng ADC để chuyển đổi giá trị tương tự sang dạng kỹ thuật số. Sau đó, gửi các giá trị kỹ thuật số đó đến MCP4725 thông qua bus I2C. Sau đó chuyển đổi các giá trị kỹ thuật số đó sang tương tự bằng cách sử dụng IC DAC MCP4725 và sau đó sử dụng chân ADC khác PA1 của STM32 để kiểm tra đầu ra tương tự của MCP4725 từ chân OUT. Cuối cùng, hiển thị cả giá trị ADC & DAC với điện áp trên màn hình LCD 16x2.
Programming STM32F103C8 for Digital to Analog Conversion
#include<Wire.h> #include <LiquidCrystal.h> #include<SoftWire.h>
Next define and initialize the LCD pins according to the LCD pins connected with the STM32F103C8
const int rs = PB11, en = PB10, d4 = PB0, d5 = PB1, d6 = PC13, d7 = PC14; LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
Then define the I2C address of the MCP4725 DAC IC. The MCP4725 DAC default I2C address is 0x60
#define MCP4725 0x60
In the void setup()
First begin the I2C communication at the pins PB7 (SDA) and PB6 (SCL) of STM32F103C8.
Wire.begin(); //Begins the I2C communication
Next set the LCD display in the 16x2 mode and display a welcome message.
lcd.begin(16,2); lcd.print("CIRCUIT DIGEST"); delay(1000); lcd.clear(); lcd.setCursor(0,0); lcd.print("STM32F103C8"); lcd.setCursor(0,1); lcd.print("DAC with MCP4725"); delay(2000); lcd.clear();
In the void loop()
1. First in buffer[0] put the control byte value (0b01000000).
(010-Sets MCP4725 in Write mode) buffer[0] = 0b01000000;
2. Following statement reads the analog value from pin PA0 and converts it into digital value ranging from 0 to4096 as ADC is 12-bit resolution and store in the variable adc.
adc = analogRead(PA0) ;
3. This following statement is a formula used to calculate the voltage from the ADC input value (0 to 4096) with the reference voltage of 3.3V.
float ipvolt = (3.3/4096.0)* adc;
4. Put the Most significant bit values in buffer[1] by shifting 4 bits to right in ADC variable, and Least significant bit values in buffer[2] by shifting 4 bits to left in adc variable.
buffer[1] = adc >> 4; buffer[2] = adc << 4;
5. The following statement reads analog value from ADC pin PA1 of STM32 that is the DAC output (MCP4725 DAC IC’s OUTPUT pin). This pin can also be connected to multimeter to check the output voltage.
unsigned int analogread = analogRead(PA1);
6. Further the voltage value from the variable analogread is calculated using the formula with the following statement.
float opvolt = (3.3/4096.0)* analogread;
7. In the same void loop () there are few other statements which are explained below
Begins the transmission with MCP4725:
Wire.beginTransmission(MCP4725);
Sends the control byte to I2C
Wire.write(buffer[0]);
Sends the MSB to I2C
Wire.write(buffer[1]);
Sends the LSB to I2C
Wire.write(buffer[2]);
Ends the transmission
Wire.endTransmission();
Now display those results in the LCD 16x2 display using lcd.print()
lcd.setCursor(0,0); lcd.print("A IP:"); lcd.print(adc); lcd.setCursor(10,0); lcd.print("V:"); lcd.print(ipvolt); lcd.setCursor(0,1); lcd.print("D OP:"); lcd.print(analogread); lcd.setCursor(10,1); lcd.print("V:"); lcd.print(opvolt); delay(500); lcd.clear();
Testing the DAC with STM32
#include<Wire.h> //Include Wire library for using I2C functions
#include<SoftWire.h>
#include <LiquidCrystal.h> //Include LCD library for using LCD display functions
#define MCP4725 0x60 //MCP4725 address as 0x60 Change yours accordingly
const int rs = PB11, en = PB10, d4 = PB0, d5 = PB1, d6 = PC13, d7 = PC14;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
unsigned int adc;
byte buffer[3];
void setup()
{
Wire.begin(); //Begins the I2C communication
lcd.begin(16,2); //Sets LCD in 16X2 Mode
lcd.print("CIRCUIT DIGEST");
delay(1000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("STM32F103C8");
lcd.setCursor(0,1);
lcd.print("DAC with MCP4725");
delay(2000);
lcd.clear();
}
void loop()
{
buffer[0] = 0b01000000; //Sets the buffer0 with control byte (010-Sets in Write mode)
adc = analogRead(PA0); //Read Analog value from pin PA0
float ipvolt = (3.3/4096.0)* adc; //Finding voltage formula
buffer[1] = adc >> 4; //Puts the most significant bit values
buffer[2] = adc << 4; //Puts the Least significant bit values
unsigned int analogread = analogRead(PA1) ; //Reads analog value from PA1
float opvolt = (3.3/4096.0)* analogread; //Finding Voltage Formula
Wire.beginTransmission(MCP4725); //Joins I2C bus with MCP4725 with 0x60 address
Wire.write(buffer[0]); //Sends the control byte to I2C
Wire.write(buffer[1]); //Sends the MSB to I2C
Wire.write(buffer[2]); //Sends the LSB to I2C
Wire.endTransmission(); //Ends the transmission
lcd.setCursor(0,0);
lcd.print("A IP:");
lcd.print(adc); //Prints the ADC value from PA0
lcd.setCursor(10,0);
lcd.print("V:"); //Prints the Input Voltage at PA0
lcd.print(ipvolt);
lcd.setCursor(0,1);
lcd.print("D OP:");
lcd.print(analogread); //Prints the ADC value from PA1 (From DAC)
lcd.setCursor(10,1);
lcd.print("V:");
lcd.print(opvolt); //Prints the Input Voltage at PA1 (From DAC)
delay(500);
lcd.clear();
}