Skip to content

Commit 2583a21

Browse files
author
Kalle Raiskila
committed
Add stm32f411e-discovery example sound_out
1 parent 9b7c2c3 commit 2583a21

File tree

4 files changed

+177
-0
lines changed

4 files changed

+177
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# README
2+
3+
This directory contains samples for the STM32F411EDISCOVERY
4+
board. This is similar to the original STM32F4DISCOVERY, but
5+
has the the STM32F411VE MCU.
6+
The board is labeled 'MB-1115 B-02'
7+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
BINARY = sound_out
2+
DEVICE=STM32F411VE
3+
include ../../Makefile.include
4+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# README
2+
3+
This example demonstrates using the oboard audio DAC on
4+
STM32F411-Discovery board.
5+
It plays a continuous 1 kHz sine wave.
6+
7+
## Board connections
8+
9+
Sepeakers attached to the 3.5mm audio jack.
10+
Note: volume is turned low, but beware of loud sounds
11+
in case of bugs (i.e. plug the headphones to your ear
12+
only after playback starts!)
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*
2+
* Example to show using I2C and I2C with libopencm3.
3+
* This is intended for the STM32F411-Discovery demoboard.
4+
* It has a CS42L22 audio DAC onboard.
5+
*
6+
* The device plays a 1kHz sine through the audio jack.
7+
*/
8+
9+
10+
#include <libopencm3/stm32/gpio.h>
11+
#include <libopencm3/stm32/i2c.h>
12+
#include <libopencm3/stm32/rcc.h>
13+
#include <libopencm3/stm32/spi.h>
14+
15+
16+
/* Test audio: 8 points of a sine.
17+
* At Fs=8kHz, this means a 1kHz audio sine
18+
* (the other channel is mute)
19+
*/
20+
#define VOL 0x0020
21+
#define D16(x) ((int16_t)(x*VOL) )
22+
//+ 0x7fff)
23+
int16_t audio[16]=
24+
{ D16(0), 0,
25+
D16(0.70711), 0,
26+
D16(1), 0,
27+
D16(0.70711), 0,
28+
D16(0), 0,
29+
D16(-0.70711),0,
30+
D16(-0.9999), 0,
31+
D16(-0.707), 0 };
32+
33+
34+
static void write_i2c_to_audiochip( uint8_t reg, uint8_t contents)
35+
{
36+
uint8_t packet[2];
37+
packet[0] = reg;
38+
packet[1] = contents;
39+
/* STM32F411 gives device address with R/W bit,
40+
* libopencm wants it without it */
41+
uint8_t address = (0x94)>>1;
42+
43+
i2c_transfer7(I2C1, address, packet, 2, NULL, 0);
44+
}
45+
46+
int main(void)
47+
{
48+
/* Set device clocks from opencm3 provided preset.*/
49+
const struct rcc_clock_scale *clocks = &rcc_hsi_configs[RCC_CLOCK_3V3_84MHZ];
50+
rcc_clock_setup_pll( clocks );
51+
52+
rcc_periph_clock_enable(RCC_GPIOA);
53+
rcc_periph_clock_enable(RCC_GPIOB);
54+
rcc_periph_clock_enable(RCC_GPIOC);
55+
rcc_periph_clock_enable(RCC_GPIOD);
56+
57+
/* Initialize "heartbeat" LED GPIO */
58+
gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO13);
59+
60+
/* I2C GPIO pins
61+
* PB6 - SCL (I2C clock)
62+
* PB9 - SDA (I2C data)
63+
* The board does not have pullups on the I2C lines, so
64+
* we use the chip internal pullups.
65+
* Also the pins must be open drain, as per I2C specification.
66+
* STM32F411 datasheet "Alternate Functions table" tells that
67+
* I2C is AlternateFucntion 4 for both pins.
68+
*/
69+
gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO6);
70+
gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO9);
71+
gpio_set_output_options(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_25MHZ, GPIO6);
72+
gpio_set_output_options(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_25MHZ, GPIO9);
73+
gpio_set_af(GPIOB, GPIO_AF4, GPIO6);
74+
gpio_set_af(GPIOB, GPIO_AF4, GPIO9);
75+
76+
/* Initialize the I2C itself.
77+
* Since we are master, we would not need to initialize slave
78+
* address, but this is the only libopencm3 API call that sets
79+
* the 'bit14 of CCR' - a bit in the I2C that is HW reset to 0,
80+
* but manual says 'must be 1' */
81+
rcc_periph_clock_enable(RCC_I2C1);
82+
i2c_peripheral_disable(I2C1);
83+
i2c_set_speed(I2C1, i2c_speed_sm_100k, clocks->apb1_frequency/1000000);
84+
i2c_set_own_7bit_slave_address(I2C1, 0);
85+
i2c_peripheral_enable(I2C1);
86+
87+
/* Initialize I2S.
88+
* I2S is implemented as a HW mode of the SPI peripheral.
89+
* Since this is a STM32F411, there is a separate I2S PLL
90+
* that needs to be enabled.
91+
*/
92+
rcc_osc_on(RCC_PLLI2S);
93+
rcc_periph_clock_enable(RCC_SPI3);
94+
i2s_disable(SPI3);
95+
i2s_set_standard(SPI3, i2s_standard_philips);
96+
i2s_set_dataformat(SPI3, i2s_dataframe_ch16_data16);
97+
i2s_set_mode(SPI3, i2s_mode_master_transmit);
98+
i2s_masterclock_enable(SPI3);
99+
/* RCC_PLLI2SCFGR configured values are:
100+
* 0x24003010 i.e.
101+
* PLLR = 2
102+
* PLLI2SN = 192
103+
* PLLI2SM = 16
104+
* And since the input is PLL source (i.e. HSI = 16MHz)
105+
* The I2S clock = 16 / 16 * 192 / 2 = 96MHz
106+
* Calculate sampling frequency from equation given in
107+
* STM32F411 reference manual:
108+
* Fs = I2Sclk/ (32*2 * ((2*I2SDIV)+ODD)*4)
109+
* I2SDIV = I2Sclk/(512*Fs)
110+
* I2SDIV=24 => 23,4 so 23 + ODD bit set
111+
*/
112+
i2s_set_clockdiv(SPI3, 23, 1);
113+
i2s_enable(SPI3);
114+
115+
116+
/* I2S pins:
117+
* Master clock: PC7
118+
* Bit clock: PC10
119+
* Data: PC12
120+
* L/R clock: PA4
121+
*/
122+
gpio_mode_setup(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO7);
123+
gpio_set_af(GPIOC, GPIO_AF6, GPIO7);
124+
gpio_mode_setup(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO10);
125+
gpio_set_af(GPIOC, GPIO_AF6, GPIO10);
126+
gpio_mode_setup(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO12);
127+
gpio_set_af(GPIOC, GPIO_AF6, GPIO12);
128+
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO4);
129+
gpio_set_af(GPIOA, GPIO_AF6, GPIO4);
130+
131+
132+
/* Initialize the Audio DAC, as per its datasheet.
133+
* CS43L22 /RESET is connected to PD4, first release it. Then write
134+
* minimum set of needed settings. */
135+
gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO4);
136+
gpio_set(GPIOD, GPIO4);
137+
write_i2c_to_audiochip(0x06, 0x04); // interface control 1: set I2S dataformat
138+
write_i2c_to_audiochip(0x02, 0x9e); // power control 1: Magic value to power up the chip
139+
140+
141+
while(1) {
142+
/* Blink the heartbeat LED */
143+
static int blinkslowdown=0;
144+
if( ++blinkslowdown == 8000) {
145+
gpio_toggle(GPIOD, GPIO13);
146+
blinkslowdown=0;
147+
}
148+
149+
for( unsigned i=0; i < sizeof(audio)/sizeof(audio[0]); i++)
150+
spi_send(SPI3, audio[i]);
151+
}
152+
return 0;
153+
}
154+

0 commit comments

Comments
 (0)