一、注意事项
标题特别注明了是SPI3,因为AT32F的SPI的这个通道比较特殊,用的时候遇到了些麻烦,所以特别的标注出来。
在调试的过程中,片选信号死活不起作用,记得前段时间用STM32F107的时候,倒是没出现这种情况,后来查看技术手册的的复用功能章节查看到如下信息:
所以,需要设置重映射。
gpio_pin_remap_config(SWJTAG_GMUX_010, TRUE);
二、ADS8028介绍
ADS8028的读写还是比较简单的,控制寄存器的WRITE置1,然后选择需要设置的通道即可。
一次片选信号,读写2个字节16bit,如下图所示:
三、读写代码如下
#include <stdint.h>
#include <string.h>
#include <rtdevice.h>
#include <drv_gpio.h>
#include <drv_spi.h>
#define AIN_NUM 8 //8路模拟量输入
#define DBG_ENABLE
#define DBG_COLOR
#define DBG_SECTION_NAME "ads"
#define DBG_LEVEL DBG_LOG
#include <rtdbg.h>
#ifndef RT_ADS_DEFAULT_SPI_CFG
#ifndef RT_ADS_SPI_MAX_HZ
#define RT_ADS_SPI_MAX_HZ 20*1000*1000
#endif
#define RT_ADS_DEFAULT_SPI_CFG \
{ \
.mode = RT_SPI_MODE_2| RT_SPI_MSB |RT_SPI_MASTER, \
.data_width = 16, \
.max_hz = RT_ADS_SPI_MAX_HZ, \
}
#endif
#define ADS_BUSY_PIN GET_PIN(B, 11)
#define ADS_RST_PIN GET_PIN(B, 10)
#define ADS_RST_HIGH() rt_pin_write(ADS_RST_PIN, PIN_HIGH)
#define ADS_RST_LOW() rt_pin_write(ADS_RST_PIN, PIN_LOW)
#define ADS_BUSY_HIGH() rt_pin_write(ADS_BUSY_PIN, PIN_HIGH)
#define ADS_BUSY_LOW() rt_pin_write(ADS_BUSY_PIN, PIN_LOW)
#define BUS_NAME "spi3"
#define CS_GPIO_X GPIOA
#define CS_GPIO_PIN GPIO_PINS_15
#define SPI_DEVICE_NAME "ads"
static struct rt_spi_device *spi_dev_ads8028;
static int rt_hw_ads8028_config(void)
{
LOG_D("start rt_hw_ads8028_config");
rt_err_t res = RT_EOK;
res = rt_hw_spi_device_attach(BUS_NAME, SPI_DEVICE_NAME, CS_GPIO_X, CS_GPIO_PIN);
if (res != RT_EOK)
{
LOG_E("Failed to attach device %s\n",SPI_DEVICE_NAME);
return res;
}
spi_dev_ads8028 = (struct rt_spi_device * )rt_device_find(SPI_DEVICE_NAME);
if (!spi_dev_ads8028)
{
LOG_E("spi find run failed! cant't find %s device!\n", SPI_DEVICE_NAME);
return RT_ERROR;
}
/* config spi */
struct rt_spi_configuration cfg = RT_ADS_DEFAULT_SPI_CFG;
rt_spi_configure(spi_dev_ads8028, &cfg);
return RT_EOK;
}
int rt_hw_ads_init(void)
{
rt_hw_ads8028_config();
rt_pin_mode(ADS_RST_PIN, PIN_MODE_OUTPUT);
ADS_RST_HIGH();
LOG_D("rt_hw_ads_init ok");
return RT_EOK;
}
//INIT_DEVICE_EXPORT(rt_hw_ads_init);
void spi_delay( void )
{
rt_hw_us_delay(10);
}
static uint8_t ADS_SendCmd(uint16_t tx, uint8_t len) {
if (rt_spi_send(spi_dev_ads8028,&tx, len) == 0)
{
LOG_E("EEPROM_WriteEnable error\r\n");
return RT_ERROR;
}
return RT_EOK;
}
static uint8_t ADS_RecvData(uint16_t *data, uint8_t len) {
uint8_t rx_data[2];
memset(rx_data,0,sizeof(rx_data));
if (rt_spi_recv(spi_dev_ads8028, rx_data, len) == 0)
{
LOG_E("EEPROM_WriteEnable error\r\n");
return RT_ERROR;
}
// LOG_D("rx_data:%02x%02x",rx_data[1],rx_data[0]);
if( data ){
*data = (rx_data[1]<<8)|rx_data[0];
}
return RT_EOK;
}
uint32_t ad_to_mv( uint16_t ad )
{
uint32_t mv;
mv = ad*2500/4095;
return mv;
}
void ADS_Read_All(uint16_t *out )
{
int data_width_len,i;
uint16_t rx_data[8];
memset(rx_data,0,sizeof(rx_data));
data_width_len = 1;
uint16_t cmd = (1<<15)|(0xff<<6);
ADS_SendCmd(cmd,data_width_len);
spi_delay();
ADS_SendCmd(0,data_width_len);
for( i=0; i<AIN_NUM; i++ ){
spi_delay();
ADS_RecvData(&rx_data[i],data_width_len);
LOG_D("rx_data[%d]:%04x",i,rx_data[i]);
if( (rx_data[i]>>12)!= i ){
out[i] = 0; //error
LOG_E("ERROR: rx_data[%d]",i);
}else{
out[i] = ad_to_mv( rx_data[i]&0xfff );
}
}
}