[ESP32]开发随笔和踩坑记录(一)
为了弥补17届智能车的遗憾,笔者准备做一个无线图传模块留给下一届以及以后的车友们,因此目前正在开发并熟悉ESP32这款单片机。
开发环境搭建
笔者用的是vscode配合esp-idf,用着还算顺手。
向工程中添加.c.h文件
我们在根目录下新建文件夹components
形式如下:
components
└─lib1
│ ├─inc
│ └─src
│ CMakeLists.txt
│ component.mk
└─lib2
│ ├─inc
│ └─src
│ CMakeLists.txt
│ component.mk
其中component.mk不需要添加内容
而每个对应的CMakeLists.txt内容如下:
file(GLOB_RECURSE srcs src/*.c)
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "inc")
这里使用了file
这个命令来将文件夹内的内容全部添加入srcs
变量中,这样就不需要一个个手敲.c文件了
SPI-master
ESP32集成了4个spi外设
SPI0
和SPI1
在内部用于访问ESP32连接的内存
SPI2
和SPI3
是通用SPI控制器,也被称为HSPI和VSPI。两者具有独立的总线信号,每条总线有三条CS线。
GPIO矩阵和IO_MUX
ESP32大多数外设信号都可以直接连接到专用的引脚,但是也可以通过GPIO矩阵将信号转换到其他任何可用的引脚。
GPIO矩阵虽然带来了灵活性但是也同样会增加输入延迟并且不能开到最大的时钟频率。
踩的一些坑
笔者在移植u8g2库的时候用逻分发现在每次发送数据前都会带个0x00,排查下来原来是因为在设备结构体中设置了command_bits成员,但是每次发送时候发送的结构体内cmd的内容为空,所以每次进行spi通信的时候开头都会跟一个8位cmd,导致不能正常的与设备通信。
像上图就是本来想只发送0x40但是实际上发送了0x00和0x40
下面是设备的一个设置结构体
typedef struct {
uint8_t command_bits; //命令的位数
uint8_t address_bits; //地址的位数
uint8_t dummy_bits; //在地址和数据之间间隔的位数
uint8_t mode; /**< SPI mode, representing a pair of (CPOL, CPHA) configuration:
- 0: (0, 0)
- 1: (0, 1)
- 2: (1, 0)
- 3: (1, 1)
*/
uint16_t duty_cycle_pos; //CLK信号的占空比
uint16_t cs_ena_pretrans;
uint8_t cs_ena_posttrans;
int clock_speed_hz;
int input_delay_ns;
int spics_io_num; //CS脚的io编号
uint32_t flags; //一些标志位
int queue_size; //传输队列的大小
transaction_cb_t pre_cb; //通信前的回调函数
transaction_cb_t post_cb; //这是通信结束后的回调函数
} spi_device_interface_config_t;
接下来看esp32的sdk中所定义的一种通信的格式:
struct spi_transaction_t {
uint32_t flags;//通信的一些设置,可以选择使用tx_buffer或者tx_data之类的,当然这里也可以做设置让单片机不发送cmd和addr从而解决问题
uint16_t cmd;
uint64_t addr;
size_t length;//以bit为单位的长度
size_t rxlength;
void *user;
union {
const void *tx_buffer;
uint8_t tx_data[4];
};
union {
void *rx_buffer;
uint8_t rx_data[4];
};
} ;
关于遇到的问题也很明了,只需要将struct spi_transaction_t
的flags与上SPI_TRANS_VARIABLE_CMD
和SPI_TRANS_VARIABLE_ADDR
即可,或者直接将spi_device_interface_config_t
中的command_bits
和address_bits
两个变量置零。