欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 资讯 > rtthread 软件SPI驱动, 支持mode0~3,MSB,LSB

rtthread 软件SPI驱动, 支持mode0~3,MSB,LSB

2025/4/17 15:31:56 来源:https://blog.csdn.net/u013866683/article/details/147047630  浏览:    关键词:rtthread 软件SPI驱动, 支持mode0~3,MSB,LSB

rtthread的软件模拟SPI用的上层PIN驱动写,由于经过层层封装,时钟频率并不会太高,200MHz的MCU跑不到1MHz的时钟频率。所以最好是在底层就模拟好,给上层用。

头文件

struct io_poSOFT
{gpio_type *port;uint16_t pin;
};
typedef struct soft_spi_ios
{struct io_poSOFT cs;struct io_poSOFT clk;struct io_poSOFT mosi;struct io_poSOFT miso;
} soft_spi_ios_t;struct soft_spi_bus_ops;typedef struct soft_spi_bus
{struct soft_spi_ios *ios;uint8_t mode;uint32_t clktk;void (*delay_us)(uint8_t us);struct soft_spi_bus_ops *ops; // NOTE 先引用后声明的只能用指针
} soft_spi_bus_t;struct soft_spi_bus_ops
{uint8_t (*transfer)(soft_spi_bus_t *bus, uint8_t data);void (*send_then_send)(soft_spi_bus_t *bus, uint8_t *sbuf1, uint8_t slen1, uint8_t *sbuf2, uint8_t slen2);void (*send_then_receive)(soft_spi_bus_t *bus, uint8_t *sbuf, uint8_t slen, uint8_t *rbuf, uint8_t rlen);
};#define SOFT_SPI_CPHA (1 << 0)                          /* bit[0]:CPHA, clock phase */
#define SOFT_SPI_CPOL (1 << 1)                          /* bit[1]:CPOL, clock polarity */
#define SOFT_SPI_LSB (0 << 2)                           /* bit[2]: 0-LSB */
#define SOFT_SPI_MSB (1 << 2)                           /* bit[2]: 1-MSB */
#define SOFT_SPI_MODE_0 (0 | 0)                         /* CPOL = 0, CPHA = 0 */
#define SOFT_SPI_MODE_1 (0 | SOFT_SPI_CPHA)             /* CPOL = 0, CPHA = 1 */
#define SOFT_SPI_MODE_2 (SOFT_SPI_CPOL | 0)             /* CPOL = 1, CPHA = 0 */
#define SOFT_SPI_MODE_3 (SOFT_SPI_CPOL | SOFT_SPI_CPHA) /* CPOL = 1, CPHA = 1 */
void soft_spi_bus_init(struct soft_spi_bus *bus, struct soft_spi_ios *ios);
void soft_spi_bus_send_then_send(struct soft_spi_bus *bus, uint8_t *sbuf1, uint8_t slen1, uint8_t *sbuf2, uint8_t slen2);
void soft_spi_bus_send_then_receive(struct soft_spi_bus *bus, uint8_t *sbuf, uint8_t slen, uint8_t *rbuf, uint8_t rlen);

源文件

#define __io_set(x) gpio_bits_set(bus->ios->x.port, bus->ios->x.pin)
#define __io_reset(x) gpio_bits_reset(bus->ios->x.port, bus->ios->x.pin)
// #define __io_read(x) ((bus->ios->x.port->idt & bus->ios->x.pin) != 0)
#define __io_read(x) gpio_input_data_bit_read(bus->ios->x.port, bus->ios->x.pin)
#define __io_write(x, y) \if (y)               \__io_set(x);     \else                 \__io_reset(x)static rt_err_t soft_spi_configure(struct rt_spi_device *device,struct rt_spi_configuration *configuration)
{struct rt_spi_bus *spi_bus = (struct rt_spi_bus *)device->bus;struct soft_spi_bus *instance = (struct soft_spi_bus *)spi_bus->parent.user_data;// NOTE 2.5Mhzinstance->mode = configuration->mode;gpio_bits_write(instance->ios->clk.port, instance->ios->clk.pin, (instance->mode & SOFT_SPI_CPOL)); // 空闲电平return RT_EOK;
}void soft_spi_bus_init(struct soft_spi_bus *bus, struct soft_spi_ios *ios)
{gpio_init_type gpio_init_struct;gpio_init_struct.gpio_pins = ios->clk.pin;gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MAXIMUM;gpio_init(ios->clk.port, &gpio_init_struct);gpio_init_struct.gpio_pins = ios->miso.pin;gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;gpio_init_struct.gpio_pull = GPIO_PULL_NONE;gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MAXIMUM;gpio_init(ios->miso.port, &gpio_init_struct);gpio_init_struct.gpio_pins = ios->mosi.pin;gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MAXIMUM;gpio_init(ios->mosi.port, &gpio_init_struct);bus->ios = ios;// bus->delay_us = spi_delay;__io_write(clk, bus->mode & SOFT_SPI_CPOL); // 空闲电平
}static uint8_t soft_spi_transfer(struct soft_spi_bus *bus, uint8_t data)
{
#define __write_bit()                    \if (bus->mode & SOFT_SPI_MSB)        \{                                    \__io_write(mosi, (data & 0x80)); \data <<= 1;                      \}                                    \else                                 \{                                    \__io_write(mosi, (data & 0x01)); \data >>= 1;                      \}
#define __read_bit()                                      \if (__io_read(miso))                                  \{                                                     \data |= (bus->mode & SOFT_SPI_MSB) ? 0x01 : 0x80; \}for (int i = 0; i < 8; i++){/*** @brief* MODE CPOL    CPHA   CLK_IDL  MISO    MOSI* 0    0       0       0       RISING  FALLING* 1    0       1       0* 2    1       0       1* 3    1       1       1*/if (bus->mode & SOFT_SPI_CPHA){// NOTE CPHA=1, CPOL=X. first edge write, second edge read__io_write(clk, !(bus->mode & SOFT_SPI_CPOL));__write_bit();__NOP();// bus->delay_us(bus->clktk);__io_write(clk, (bus->mode & SOFT_SPI_CPOL));// bus->delay_us(bus->clktk);__NOP();__read_bit();}else{// NOTE CPHA=0, CPOL=X.  first edge read, second edge write__write_bit();__io_write(clk, !(bus->mode & SOFT_SPI_CPOL));__NOP();// bus->delay_us(bus->clktk);__read_bit();__io_write(clk, (bus->mode & SOFT_SPI_CPOL));__NOP();// bus->delay_us(bus->clktk);}}// LOG_D("input data = %04x\n",gpio_input_data_read(bus->ios->miso.port));LOG_D("output data = %04x\n", data);return data;
}static rt_uint32_t soft_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
{struct rt_spi_bus *at32_spi_bus = (struct rt_spi_bus *)device->bus;struct soft_spi_bus *bus = (struct soft_spi_bus *)at32_spi_bus->parent.user_data;struct io_poSOFT *cs = device->parent.user_data;rt_size_t message_length = 0, already_send_length = 0;rt_uint16_t send_length = 0;rt_uint8_t *recv_buf;const rt_uint8_t *send_buf;RT_ASSERT(device != NULL);RT_ASSERT(message != NULL);// rt_kprintf("device = %08x\n",device);/* take cs */if (message->cs_take){// NOTE 这个板子CS需要取反,否则是CS是低电平// gpio_bits_reset(cs->port, cs->pin);gpio_bits_set(cs->port, cs->pin);// LOG_D("spi take cs\n");}message_length = message->length;recv_buf = message->recv_buf;send_buf = message->send_buf;while (message_length){/* the HAL library use uint16 to save the data length */if (message_length > 65535){send_length = 65535;message_length = message_length - 65535;}else{send_length = message_length;message_length = 0;}/* calculate the start address */already_send_length = message->length - send_length - message_length;send_buf = (rt_uint8_t *)message->send_buf + already_send_length;recv_buf = (rt_uint8_t *)message->recv_buf + already_send_length;/* start once data exchange in dma mode */if (message->send_buf && message->recv_buf){for (uint8_t i = 0; i < send_length; i++){recv_buf[i] = soft_spi_transfer(bus, send_buf[i]);}}else if (message->send_buf){for (uint8_t i = 0; i < send_length; i++){LOG_D("****SEND****\n");LOG_D("soft spi send data:%02x\n", send_buf[i]);soft_spi_transfer(bus, send_buf[i]);}}else{memset((void *)recv_buf, 0xff, send_length);for (uint8_t i = 0; i < send_length; i++){LOG_D("****READ****\n");recv_buf[i] = soft_spi_transfer(bus, 0x00);LOG_D("soft spi read data:%02x\n", recv_buf[i]);}}}/* release cs */if (message->cs_release){gpio_bits_reset(cs->port, cs->pin);}return message->length;
}static struct rt_spi_ops at32_soft_spi_ops ={soft_spi_configure,soft_spi_xfer};int at_sf_spi_init(void)
{rt_err_t result;struct rt_spi_bus *rt_soft_spi_bus = RT_NULL;rt_soft_spi_bus = (struct rt_spi_bus *)rt_malloc(sizeof(struct rt_spi_bus));static soft_spi_bus_t soft_spi_bus = {.mode = SOFT_SPI_MODE_3 | SOFT_SPI_MSB};static soft_spi_ios_t soft_spi_bus_io ={.mosi = {GPIOB, GPIO_PINS_10},.miso = {GPIOA, GPIO_PINS_2},.clk = {GPIOA, GPIO_PINS_3},};soft_spi_bus_init(&soft_spi_bus, &soft_spi_bus_io);rt_soft_spi_bus->parent.user_data = &soft_spi_bus;result = rt_spi_bus_register(rt_soft_spi_bus, "sspi", &at32_soft_spi_ops);LOG_D("sspi init result:%d\n", result);return result;
}// INIT_BOARD_EXPORT(rt_soft_spi_init);
INIT_BOARD_EXPORT(at_sf_spi_init);

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词