/* Use DAC_MCP4725 of the Edubase board via I2C. * * The program generates sinewave output through DAC, which * is connected via I2C. The I2C connections are: * I2C1_SCL - PB08 * I2C1_SDA - PB09 * * Put speaker select jumper on DAC and you will hear the tone. * */ #include "stm32f4xx.h" #define SLAVE_ADDR 0x60 /* 1100 xx0. */ void I2C1_init(void); int I2C1_burstWrite(char saddr, char maddr, int n, char* data); void MCP4725_data(int n); const static int sineWave[] = {2047,3071,3820,4094,3820,3071, 2047,1024, 274, 0, 274,1024}; int main(void) { int i; I2C1_init(); for (;;) { /* infinite loop */ for (i = 0; i < sizeof(sineWave)/sizeof(int); i++) { MCP4725_data(sineWave[i]); } } } void MCP4725_data(int n) { char data[2]; data[1] = (n << 4) & 0xFF; data[0] = (n >> 4) & 0xFF; I2C1_burstWrite(SLAVE_ADDR, 0x40, 2, data); } /* configure UCB1 as I2C */ void I2C1_init(void) { RCC->AHB1ENR |= 2; /* Enable GPIOB clock */ RCC->APB1ENR |= 0x00200000; /* Enable I2C1 clock */ /* configure PB8, PB9 pins for I2C1 */ GPIOB->AFR[1] &= ~0x000000FF; /* PB8, PB9 I2C1 SCL, SDA */ GPIOB->AFR[1] |= 0x00000044; GPIOB->MODER &= ~0x000F0000; /* PB8, PB9 use alternate function */ GPIOB->MODER |= 0x000A0000; GPIOB->OTYPER |= 0x00000300; /* output open-drain */ GPIOB->PUPDR &= ~0x000F0000; /* with pull-ups */ GPIOB->PUPDR |= 0x00050000; I2C1->CR1 = 0x8000; /* software reset I2C1 */ I2C1->CR1 &= ~0x8000; /* out of reset */ I2C1->CR2 = 0x0010; /* peripheral clock is 16 MHz */ I2C1->CCR = 80; /* standard mode, 100kHz clock */ I2C1->TRISE = 17; /* maximum rise time */ I2C1->CR1 |= 0x0001; /* enable I2C1 module */ } /* Use burst write to write multiple bytes to consecutive locations * burst write: S-(slaveAddr+w)-ACK-memAddr-ACK-data-ACK...-data-ACK-P */ int I2C1_burstWrite(char saddr, char maddr, int n, char* data) { int i; volatile int tmp; while (I2C1->SR2 & 2); /* wait until bus not busy */ I2C1->CR1 &= ~0x800; /* disable POS */ I2C1->CR1 |= 0x100; /* generate start */ while (!(I2C1->SR1 & 1)); /* wait until start flag is set */ I2C1->DR = saddr << 1; /* transmit slave address */ while (!(I2C1->SR1 & 2)); /* wait until addr flag is set */ tmp = I2C1->SR2; /* clear addr flag */ while (!(I2C1->SR1 & 0x80)); /* wait until data register empty */ I2C1->DR = maddr; /* send memory address */ /* write all the data */ for (i = 0; i < n; i++) { while (!(I2C1->SR1 & 0x80)); /* wait until data register empty */ I2C1->DR = *data++; /* transmit memory address */ } while (!(I2C1->SR1 & 4)); /* wait until transfer finished */ I2C1->CR1 |= 0x200; /* generate stop */ return 0; } /* 16 MHz SYSCLK */ void delayMs(int n) { int i; for (; n > 0; n--) for (i = 0; i < 3195; i++) ; }