• ESP32-硬件SPI读取MCP3208


    其实驱动也不是针对ESP32,任何芯片去读都可以用下面方法。下面是以esp32为例。

    准备条件:

    1-确认自己的spi连线没有问题

    2-确认自己的spi驱动没有问题

    下面先看看MCP3208的手册:

     1-通信速度,先确认自己芯片的最大spi速度。esp32 -spi初始化的时候不要超过这个速度。

    2-然后看时序图

    2-1 分析一下时序图,

    发送:我们发送的第一个字节的1-5bit是我们要关注的,

    第一位是开始,没细看,直接写1

    第二位是singl/diff,其实就是单边采样和差分采样,我们只看单边的。写1

    第3-5位,即D2-D0位就是通道的数据位,根据真值表可以写出第一个字节的值,分别对应8个通道。

    uint8_t adc_ch[]={0xC0,0xC8,0xD0,0xD8,0xE0,0xE8,0xF0,0xF8};

     后面3位无意义不关注。后面发送的数据无意义。0xFF即可。

    接收:从时序图可以看出,接收的第一个字节有一个B11数据,即adc数据的第12位。

    后面的数据则是adc数据的剩下11位。

    读取的整体思路

    先发送第一个带通道的字节,得到adc的第12位,

    然后发送一个0xff,得到11-4位

    然后发送一个0xff,得到3-1位。

    至此12位数据全部得到,重新组合即可。

    编写读取函数:驱动是从之前lcd驱动移植的,会有冗余代码。

    1. #ifndef _MSPI_H_
    2. #define _MSPI_H_
    3. #include "driver/spi_master.h"
    4. #include "freertos/FreeRTOS.h"
    5. #include "freertos/task.h"
    6. #define PIN_NUM_MISO 12
    7. #define PIN_NUM_MOSI 13
    8. #define PIN_NUM_CLK 14
    9. #define PIN_NUM_CS 15
    10. #define PIN_NUM_DC 21
    11. #define PIN_NUM_RST 18
    12. #define PIN_NUM_BCKL 5
    13. #define PARALLEL_LINES 16
    14. #define SPI_ADC_CH0 0
    15. #define SPI_ADC_CH1 1
    16. #define SPI_ADC_CH2 2
    17. #define SPI_ADC_CH3 3
    18. #define SPI_ADC_CH4 4
    19. #define SPI_ADC_CH5 5
    20. #define SPI_ADC_CH6 6
    21. #define SPI_ADC_CH7 7
    22. void lcd_spi_pre_transfer_callback(spi_transaction_t *t);
    23. //spi主机初始化
    24. void spi_master_init();
    25. //spi从机初始化
    26. void spi_slave_init();
    27. esp_err_t spi_write( uint8_t *data, int len);
    28. esp_err_t spi_read(uint8_t *data);
    29. esp_err_t spi_read_adc(uint8_t *sdata,uint8_t *rdata);
    30. short spi_read_adc_ch(uint8_t ch);
    31. #endif
    1. #include "driver/gpio.h"
    2. #include "mspi.h"
    3. static spi_device_handle_t spi;
    4. static spi_bus_config_t buscfg={
    5. .miso_io_num=PIN_NUM_MISO,
    6. .mosi_io_num=PIN_NUM_MOSI,
    7. .sclk_io_num=PIN_NUM_CLK,
    8. .quadwp_io_num=-1,
    9. .quadhd_io_num=-1,
    10. .max_transfer_sz=1,
    11. };
    12. static spi_device_interface_config_t devcfg={
    13. .clock_speed_hz=100*1000, //Clock out at 10 MHz
    14. // .clock_speed_hz=80*1000*1000,
    15. .mode=0, //SPI mode 0
    16. //.cs_ena_pretrans=1,
    17. //.cs_ena_posttrans=1,
    18. .spics_io_num=PIN_NUM_CS, //CS pin
    19. .queue_size=5, //We want to be able to queue 7 transactions at a time
    20. //.pre_cb=lcd_spi_pre_transfer_callback, //Specify pre-transfer callback to handle D/C line
    21. };
    22. void lcd_spi_pre_transfer_callback(spi_transaction_t *t)
    23. {
    24. int dc=(int)t->user;
    25. //gpio_set_level(PIN_NUM_DC, dc);
    26. }
    27. //spi主机初始化
    28. void spi_master_init()
    29. {
    30. esp_err_t ret;
    31. //Initialize the SPI bus
    32. ret=spi_bus_initialize(HSPI_HOST, &buscfg, 1);
    33. ESP_ERROR_CHECK(ret);
    34. //Attach the LCD to the SPI bus
    35. ret=spi_bus_add_device(HSPI_HOST, &devcfg, &spi);
    36. ESP_ERROR_CHECK(ret);
    37. }
    38. //spi从机初始化
    39. void spi_slave_init()
    40. {
    41. }
    42. esp_err_t spi_write(uint8_t *data, int len)
    43. {
    44. esp_err_t ret;
    45. spi_transaction_t t={0};
    46. if (len==0) return 0; //no need to send anything
    47. //memset(&t, 0, sizeof(t)); //Zero out the transaction
    48. //gpio_set_level(PIN_NUM_CS, 0);
    49. t.length=len*8; //Len is in bytes, transaction length is in bits.
    50. t.tx_buffer=data; //Data
    51. //t.user=(void*)1; //D/C needs to be set to 1
    52. ret=spi_device_polling_transmit(spi, &t); //Transmit!
    53. assert(ret==ESP_OK); //Should have had no issues.
    54. //gpio_set_level(PIN_NUM_CS, 1);
    55. return ret;
    56. }
    57. esp_err_t spi_read(uint8_t *data)
    58. {
    59. spi_transaction_t t={0};
    60. //gpio_set_level(PIN_NUM_CS, 0);
    61. //memset(&t, 0, sizeof(t));
    62. t.length=8;
    63. t.flags = SPI_TRANS_USE_RXDATA;
    64. //t.user = (void*)1;
    65. esp_err_t ret = spi_device_polling_transmit(spi, &t);
    66. assert( ret == ESP_OK );
    67. *data = t.rx_data[0];
    68. //gpio_set_level(PIN_NUM_CS, 1);
    69. return ret;
    70. }
    71. esp_err_t spi_read_adc(uint8_t *sdata,uint8_t *rdata)
    72. {
    73. spi_transaction_t t={0};
    74. //gpio_set_level(PIN_NUM_CS, 0);
    75. //memset(&t, 0, sizeof(t));
    76. t.length=8*3
    77. ;
    78. t.tx_buffer=sdata;
    79. t.flags = SPI_TRANS_USE_RXDATA;
    80. //t.user = (void*)1;
    81. esp_err_t ret = spi_device_polling_transmit(spi, &t);
    82. assert( ret == ESP_OK );
    83. rdata[0] = t.rx_data[0];
    84. rdata[1] = t.rx_data[1];
    85. rdata[2] = t.rx_data[2];
    86. //gpio_set_level(PIN_NUM_CS, 1);
    87. return ret;
    88. }
    89. short spi_read_adc_ch(uint8_t ch)
    90. {
    91. short ADC_RE;
    92. uint8_t adc_ch[]={0xC0,0xC8,0xD0,0xD8,0xE0,0xE8,0xF0,0xF8};
    93. uint8_t spi_sdata1[3]={0xE0,0xff,0xff};
    94. uint8_t spi_data1[3] ={0};
    95. spi_sdata1[0]=adc_ch[ch];
    96. spi_read_adc((uint8_t *)spi_sdata1,(uint8_t *)spi_data1);
    97. int v_adc =(spi_data1[0]&0x01)<<11|spi_data1[1]<<3|(spi_data1[2]&0xe0)>>4;
    98. ADC_RE = v_adc*3300/4095;
    99. return ADC_RE;
    100. }

     使用:使用spi_read_adc_ch时先初始化spi。

    1. int i_adc =spi_read_adc_ch(SPI_ADC_CH3);
    2. int v_adc =spi_read_adc_ch(SPI_ADC_CH4);
    3. printf("esp32-v: %d I:%d, spi-v:%d I:%d\r\n",volt,i_v,v_adc,i_adc);

    运行效果:

  • 相关阅读:
    PMP考试通关宝典-敏捷专题
    C++开发面试之——C++11新特性20问
    noip游记
    NLP实践!文本语法纠错模型实战,搭建你的贴身语法修改小助手 ⛵
    JS 封装节流(后期优化)
    痞子衡嵌入式:介绍i.MXRT定时器PIT的多通道链接模式及其在coremark测试工程里的应用
    Linux C/C++ 处理命令行参数
    性能调优——小小的log大大的坑
    CS5801|替代LT6711A|HDMI转DP转接线方案|HDMI转DP带供电芯片方案
    搜维尔科技:AR/VR技术对制造业劳动力危机的影响
  • 原文地址:https://blog.csdn.net/HES_C/article/details/126125847