嵌入式 - RAM10
一、SPI
串行外设总线 -- 同步全双工(同时收发)
1. 通信
SPI是一种高速的、全双工、同步的通信总线(一主多从),并且在芯片的 管脚上只占用四根线(四线制),节约了芯片的管脚,同时为PCB 的 布局上节省空间,提供方便。
SPI使用的线:串行时钟线(SCK)、主机输入/ 从机输出数据线MISO、主机输出/从机输入数据线MOSI 、低电平有效的从机选择线SS
SPI 的工作模式:主模式和从模式
主机(master) --(SCLK,MOSI,MISO,CS / SS片选)-- 从机(slaver n)
2. 时序
CPOL -- polarity 时钟极性,工作模式:空闲时为低电平0 / 空闲时为高电平1
CPHA -- phase 时钟相位,工作模式:第一个边沿采集0 / 第二个边沿采集1
模式 | CPOL | CPHA | 空闲状态(极性) | 采样时刻(相位) |
0 | 0 | 0 | 空闲低电平 | 时钟的第一个上升沿 |
1 | 0 | 1 | 空闲低电平 | 时钟的第二个下降沿 |
2 | 1 | 0 | 工作高电平 | 时钟的第一个下降沿 |
3 | 1 | 1 | 工作高电平 | 时钟的第二个上升沿 |
SPI速率:100K ~ 100M(高速)
I2C速率:3.4Mbps(中速)
3. 配置参数
1. 读写时序
1. 模式
CPOL:1,空闲时(刚开始和结束时)为高电平
CPHA:1,第二边沿采集②
此时CPOL : CPHA = 11 = 3 为模式3
2. 延时
DELAY:片选(CS)开始到时钟(SCLK)产生边沿的时间
一般为0.5 ~ 1 SCLK时钟周期
2. 通信速率
速率f(SCLK) = 5MHz
3. 通信模型
三线模型:
4. 配置
1. 初始化
1. 引脚特性
IOMUXC_SetPinMux(IOMUXC_UART2_RX_DATA_ECSPI3_SCLK, 1);
IOMUXC_SetPinMux(IOMUXC_UART2_RTS_B_ECSPI3_MISO, 1);
IOMUXC_SetPinMux(IOMUXC_UART2_CTS_B_ECSPI3_MOSI, 1);
IOMUXC_SetPinMux(IOMUXC_UART2_TX_DATA_GPIO1_IO20, 1);
2. 电气特性
IOMUXC_SetPinConfig(IOMUXC_UART2_RX_DATA_ECSPI3_SCLK, 0x10B0);
IOMUXC_SetPinConfig(IOMUXC_UART2_RTS_B_ECSPI3_MISO, 0x10B0);
IOMUXC_SetPinConfig(IOMUXC_UART2_CTS_B_ECSPI3_MOSI, 0x10B0);
IOMUXC_SetPinConfig(IOMUXC_UART2_TX_DATA_GPIO1_IO20, 0x10B0);
3. 控制寄存器
1. ECSPI->CONREG,配置速率等
ECSPI3->CONREG = (0x7 << 20) | (3 << 12) | (2 << 8) | (1 << 4) | (1 << 3) | (1 << 0);
ECSPI->CONREG |= (1 << 0);
一般使能需要在最后单独配置,但这里说明了(0位 EN)需要在配置其他寄存器(CONFIGREG)之前置1,所以放在同一句实现
2. ECSPI3->CONFIGREG,配置极性和相位等
ECSPI3->CONFIGREG = (1 << 20) | (1 << 4) | (1 << 0);
2. 写
发送后读取本次发送产生的废数据后,将其丢弃掉,为后续读取数据做准备
void spi3_write(unsigned char data)
{while(!(ECSPI3->STATREG & (1 << 0)));ECSPI3->TXDATA = data;while(!(ECSPI3->STATREG & (1 << 3)));data = ECSPI3->RXDATA;
}
ECSPI3->RXDATA
ECSPI3->STATREG,第0位判断是否发送完毕,第3位判断是否接收到数据
3. 读
发送一个无效数据,不用处理后,开始读取
unsigned char spi3_read(void)
{unsigned char data = 0;while(!(ECSPI3->STATREG & (1 << 0)));ECSPI3->TXDATA = 0xFF;while(!(ECSPI3->STATREG & (1 << 3)));data = ECSPI3->RXDATA;return data;
}
ECSPI3->TXDATA
4. 同时读写(实现全双工)
// 发送data,接收0xFF
unsigned char spi3_transfer(unsigned char data)
{unsigned char recv_data = 0;while(!(ECSPI3->STATREG & (1 << 0)));ECSPI3->TXDATA = data;while(!(ECSPI3->STATREG & (1 << 3)));recv_data = ECSPI3->RXDATA;return recv_data;
}
5. adxl345
1. 初始化
void adxl345_init(void)
{adxl_write(0x2E, 0x08); // 寄存器0x2E中断配置为不激活,不需要中断adxl_write(0x2C, 0x0B); // 寄存器0x2C速率配置为0x0B-1011-200速率0000 1011adxl_write(0x2D, 0x0B); // 寄存器0x2D休眠配置adxl_write(0x31, 0x08); // 寄存器0x80量程配置
}
速率配置
速率快就功耗高,默认值0x0A -- 1010 -- 100速率
配置为0x0B -- 1011 -- 200速率
休眠配置
中断配置
inactivity不激活
量程配置
3线SPI,全分辨率模式,范围设置00 - ±2g
2. 写
void adxl_write(unsigned char reg_addr, unsigned char data)
{gpio_write(GPIO1, 20, 0);spi3_transfer(reg_addr);spi3_transfer(data);gpio_write(GPIO1, 20, 1);
}
3. 读
unsigned char adxl_read(unsigned char reg_addr)
{unsigned char data = 0;gpio_write(GPIO1, 20, 0);spi3_transfer(reg_addr | 0x80); // 将最高位置1data = spi3_transfer(0xFF);gpio_write(GPIO1, 20, 1);return data;
}
4. 实现读写数据
typedef struct __adxl_data
{unsigned short x;unsigned short y;unsigned short z;
}adxl_data_t;void adxl345_read(adxl_data_t *data)
{data->x = adxl_read(0x32);data->x |= (adxl_read(0x33) << 8);data->y = adxl_read(0x34);data->y |= (adxl_read(0x35) << 8);data->z = adxl_read(0x36);data->z |= (adxl_read(0x37) << 8);
}
main.c
spi3_init();
adxl345_init();unsigned char data = adxl_read(0);
char buf[40] = {0};sprintf(buf, "devid:%02X", data);
lcd_show_string(100, 100, strlen(buf) * 16, 32, 32, buf);while (1)
{adxl_data_t data = {0};adxl345_read(&data);sprintf(buf, "adxl = x:y:z = %d:%d:%d", data.x, data.y, data.z);lcd_show_string(100, 200, strlen(buf) * 16, 32, 32, buf);
}