@@ -198,6 +198,194 @@ void Audio_SelectStation(uint16_t new_stationID) {
198
198
}
199
199
```
200
200
201
+ ### OLED底层驱动
202
+
203
+ OLED底层驱动还是使用了我的[ 祖传代码] ( https://github.com/kaidegit/HWDrivers4MCU/tree/main/OLED_SSD1306_i2c ) ,虽然是i2c的,但是稍微改改发送接口,从spi发送就可以正常使用了。
204
+
205
+ ``` c++
206
+ void MY_SPI_Init () {
207
+ spi_bus_config_t buscfg = {
208
+ .miso_io_num=-1,
209
+ .mosi_io_num=OLED_MOSI_Pin,
210
+ .sclk_io_num=OLED_CLK_Pin,
211
+ .quadwp_io_num=-1,
212
+ .quadhd_io_num=-1,
213
+ .max_transfer_sz=0
214
+ };
215
+ spi_device_interface_config_t devcfg = {
216
+ .clock_speed_hz=1 * 1000 * 1000, //Clock out at 1 MHz
217
+ .mode=0, //SPI mode 0
218
+ .spics_io_num=-1, //CS pin
219
+ .queue_size=7, //We want to be able to queue 7 transactions at a time
220
+ };
221
+ ESP_ERROR_CHECK (spi_bus_initialize (OLED_SPI_HOST, &buscfg, SPI_DMA_DISABLED));
222
+ ESP_ERROR_CHECK(spi_bus_add_device(OLED_SPI_HOST, &devcfg, &oled_spi_handle));
223
+ }
224
+
225
+ spi_device_handle_t oled_spi_handle;
226
+
227
+ void oled_send (uint8_t dc, uint8_t data) {
228
+ spi_transaction_t t = {0};
229
+ t.length = 8;
230
+ t.tx_buffer = &data;
231
+ gpio_set_level(OLED_DC_Pin, dc == 0x40);
232
+ spi_device_polling_transmit(oled_spi_handle, &t);
233
+ }
234
+ ```
235
+
236
+ ### FM底层驱动
237
+
238
+ 这款FM芯片有个坑,它并非像传统的i2c设备一样,可以通过发送设备地址-发送寄存器地址-读或者写值这种操作方法来操作,而是只能顺序读取或者写入所有寄存器数据,具体可以参考数据手册。
239
+
240
+ 由于没能找到比较好的驱动,我这里参考github上一个适配于arduino的程序自己写了一个较为简陋的驱动
241
+
242
+ ```c++
243
+ struct RDA_Handler RDA5807;
244
+
245
+ RADIO_FREQ FMStationList[50] = {0};
246
+ uint16_t FMStationNum = 0;
247
+
248
+ void RDA_ReadAllInfo() {
249
+ i2c_cmd_handle_t cmd = i2c_cmd_link_create();
250
+ i2c_master_start(cmd);
251
+ i2c_master_write_byte(cmd, 0x21, 1);
252
+ // from 0x0A high to 0x0C low
253
+ uint8_t i2c_data_array[6];
254
+ // read 0x0A
255
+ i2c_master_read_byte(cmd, i2c_data_array + 0, 0);
256
+ i2c_master_read_byte(cmd, i2c_data_array + 1, 0);
257
+ // read 0x0B
258
+ i2c_master_read_byte(cmd, i2c_data_array + 2, 0);
259
+ i2c_master_read_byte(cmd, i2c_data_array + 3, 0);
260
+ // read 0x0C
261
+ i2c_master_read_byte(cmd, i2c_data_array + 4, 0);
262
+ i2c_master_read_byte(cmd, i2c_data_array + 5, 1);
263
+ i2c_master_stop(cmd);
264
+ i2c_master_cmd_begin(FM_I2C_HOST, cmd, 1000 / portTICK_RATE_MS);
265
+ i2c_cmd_link_delete(cmd);
266
+ RDA5807.radioInfo.rds = i2c_data_array[0] & 0x80;
267
+ uint16_t readChan = ((i2c_data_array[0] & 0x03) << 8) + i2c_data_array[1];
268
+ switch (RDA5807.band) {
269
+ case RADIO_BAND_US:
270
+ RDA5807.freq = RDA5807.channelSpacing * readChan + 87 * 1000;
271
+ break;
272
+ case RADIO_BAND_JP:
273
+ case RADIO_BAND_WW:
274
+ RDA5807.freq = RDA5807.channelSpacing * readChan + 76 * 1000;
275
+ break;
276
+ case RADIO_BAND_EE:
277
+ RDA5807.freq = RDA5807.channelSpacing * readChan + 65 * 1000;
278
+ }
279
+ RDA5807.radioInfo.rssi = i2c_data_array[2] >> 2;
280
+ }
281
+
282
+ void RDA_WriteAllInfo() {
283
+ i2c_cmd_handle_t cmd = i2c_cmd_link_create();
284
+ i2c_master_start(cmd);
285
+ i2c_master_write_byte(cmd, 0x20, 1);
286
+ for (uint8_t i = 2; i < 8; i++) {
287
+ i2c_master_write_byte(cmd, RDA5807.regList[i] >> 8, 1);
288
+ i2c_master_write_byte(cmd, RDA5807.regList[i] & 0xff, 1);
289
+ }
290
+ i2c_master_stop(cmd);
291
+ i2c_master_cmd_begin(FM_I2C_HOST, cmd, 1000 / portTICK_RATE_MS);
292
+ i2c_cmd_link_delete(cmd);
293
+ }
294
+
295
+ void RDA_Init() {
296
+ RDA5807.channelSpacing = 100;
297
+ // Reg 0x00 and 0x01 are not used
298
+ RDA5807.regList[0] = 0;
299
+ RDA5807.regList[1] = 0;
300
+ RDA5807.regList[2] = 0b11000000 << 8 | 0b00000011;
301
+ RDA5807.regList[3] = 0b00000000 << 8 | 0b00000000;
302
+ RDA5807.regList[4] = 0b00001000 << 8 | 0b00000000;
303
+ RDA5807.regList[5] = 0b10000100 << 8 | 0b11010100;
304
+ RDA5807.regList[6] = 0b00000000 << 8 | 0b00000000;
305
+ RDA5807.regList[7] = 0b00000000 << 8 | 0b00000000;
306
+
307
+ RDA_WriteAllInfo();
308
+ RDA_Reset();
309
+ }
310
+
311
+ void RDA_Reset() {
312
+ RDA5807.regList[RADIO_REG_CTRL] |= RADIO_REG_CTRL_RESET;
313
+ RDA_WriteAllInfo();
314
+ vTaskDelay(100 / portTICK_RATE_MS);
315
+ RDA5807.regList[RADIO_REG_CTRL] &= !RADIO_REG_CTRL_RESET;
316
+ RDA_WriteAllInfo();
317
+ }
318
+
319
+ void RDA_SetBandFrequency(enum RADIO_BAND newBand, RADIO_FREQ newFreq) {
320
+ RDA_SetBand(newBand);
321
+ RDA_SetFrequency(newFreq);
322
+ }
323
+
324
+ void RDA_SetFrequency(RADIO_FREQ newFreq) {
325
+ RADIO_FREQ freqHigh, freqLow;
326
+ switch (RDA5807.band) {
327
+ case RADIO_BAND_US:
328
+ freqLow = 87000;
329
+ freqHigh = 108000;
330
+ break;
331
+ case RADIO_BAND_JP:
332
+ freqLow = 76000;
333
+ freqHigh = 91000;
334
+ break;
335
+ case RADIO_BAND_WW:
336
+ freqLow = 76000;
337
+ freqHigh = 108000;
338
+ break;
339
+ case RADIO_BAND_EE:
340
+ freqLow = 65000;
341
+ freqHigh = 76000;
342
+ break;
343
+ default:
344
+ freqLow = 65000;
345
+ freqHigh = 108000;
346
+ break;
347
+ }
348
+ if (newFreq < freqLow) newFreq = freqLow;
349
+ if (newFreq > freqHigh) newFreq = freqHigh;
350
+ uint16_t regChannel = RDA5807.regList[RADIO_REG_CHAN] &
351
+ (RADIO_REG_CHAN_SPACE | RADIO_REG_CHAN_BAND);
352
+ uint16_t newChannel = (newFreq - freqLow) / RDA5807.channelSpacing;
353
+ regChannel += RADIO_REG_CHAN_TUNE; // enable tuning
354
+ regChannel |= newChannel << 6;
355
+ RDA5807.regList[RADIO_REG_CTRL] |=
356
+ RADIO_REG_CTRL_OUTPUT | RADIO_REG_CTRL_UNMUTE |
357
+ RADIO_REG_CTRL_RDS | RADIO_REG_CTRL_ENABLE; // | RADIO_REG_CTRL_NEW
358
+ RDA5807.regList[RADIO_REG_CHAN] = regChannel;
359
+ RDA_WriteAllInfo();
360
+ }
361
+
362
+ void RDA_SetBand(enum RADIO_BAND newBand) {
363
+ RDA5807.band = newBand;
364
+ switch (newBand) {
365
+ case RADIO_BAND_US:
366
+ RDA5807.regList[RADIO_REG_CHAN] &= !RADIO_REG_CHAN_BAND;
367
+ RDA5807.regList[RADIO_REG_CHAN] |= RADIO_REG_CHAN_BAND_US;
368
+ break;
369
+ case RADIO_BAND_JP:
370
+ RDA5807.regList[RADIO_REG_CHAN] &= !RADIO_REG_CHAN_BAND;
371
+ RDA5807.regList[RADIO_REG_CHAN] |= RADIO_REG_CHAN_BAND_JP;
372
+ break;
373
+ case RADIO_BAND_WW:
374
+ RDA5807.regList[RADIO_REG_CHAN] &= !RADIO_REG_CHAN_BAND;
375
+ RDA5807.regList[RADIO_REG_CHAN] |= RADIO_REG_CHAN_BAND_WW;
376
+ break;
377
+ case RADIO_BAND_EE:
378
+ RDA5807.regList[RADIO_REG_CHAN] &= !RADIO_REG_CHAN_BAND;
379
+ RDA5807.regList[RADIO_REG_CHAN] |= RADIO_REG_CHAN_BAND_EE;
380
+ break;
381
+ default:
382
+ break;
383
+ }
384
+ RDA5807.regList[RADIO_REG_CHAN] |= RADIO_REG_CHAN_SPACE_100;
385
+ RDA_WriteAllInfo();
386
+ }
387
+ ```
388
+
201
389
### GUI部分
202
390
203
391
GUI部分我新建了一个线程,根据各个标志位来判断模式,显示各类信息
@@ -447,5 +635,9 @@ static void gpio_isr_handler(void *arg) {
447
635
}
448
636
```
449
637
638
+ ## 感悟与心得
639
+
640
+ 初次上手乐鑫,我感觉乐鑫的例程还是十分丰富的。由于在使用STM32时,我已经对cmake有一个初步的掌握了,转到乐鑫的esp-idf时就显得不那么费力了,也能继续用我熟悉的CLion了。但是似乎对于那些只熟悉MDK-ARM或者IAR的嵌入式开发者,转而使用乐鑫idf就似乎显得要学的东西有点多了。
450
641
642
+ 再对比下当下STM32和ESP32的价格和性能,ESP32还真是便宜大碗啊,还有着WiFi功能。尽管ESP的库比ST的Hal库庞大亿点,深入调试略微麻烦,有些库甚至封装成了lib,但还是在群友的帮助下解决了问题。
451
643
0 commit comments