根据电路板的连线图和手册中的寄存器定义,可以先写一波SPI_AD7908相关的宏。
#define AD7908_CS PAout(8) //AD7908片选信号,低电平有效
#define AD7908_MISO PBin(14)
#define AD7908_MOSI PBout(15)
#define AD7908_CLK PBout(13)
#define SPI_AD7908_WRITE(n) (n<<11) //0=read 1=write
#define SPI_AD7908_ADD(n) (n<<6) //n:0~7 读取通道
#define SPI_AD7908_PM(n) (n<<4) //n:0~3 0:无效,1:自动关断,2:完全关断,3:正常工作
#define SPI_AD7908_SEQ(n) (n<<10)// 配合SHADOW使用
#define SPI_AD7908_SHADOW(n) (n<<3) // 配合SEQ使用 00:序列未使用 11:连续通道序列连续转换
#define SPI_AD7908_RANGE(n) (n<<1)// 输入范围 0:0~2*Ref , 1:0~Ref
#define SPI_AD7908_CODING(n) (n<<0)// 0:二进制补码输出, 1:二进制输出
void AD7908_Init(void);
uint16_t SPI_AD7908_Write_Control(uint8_t writeread, uint8_t Channel);
uint16_t SPI_ReadWrite(uint16_t TxData);
AD7908_Init
初始化成普通IO输入输出,SPI_AD7908_Write_Control
则根据定义生成相应的写入参数,SPI_ReadWrite
则根据时序对参数进行写入,和对数据进行读取。
此处可以参考AD7908时序图:
void AD7908_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //PORTA时钟使能 片选引脚
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //PORTA时钟使能 片选引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; // PA8 推挽
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA, GPIO_Pin_8);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15; // PA8 推挽
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_15);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; // PA8 推挽
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
AD7908_CS = 1; //SPI AD7908不选中
AD7908_CLK = 1;
}
uint16_t SPI_AD7908_Write_Control(uint8_t writeread, uint8_t Channel)//控制寄存器中写值
{
u16 dat_16 = 0;
if (writeread == 1) //write
dat_16 = SPI_AD7908_WRITE(writeread) | \
SPI_AD7908_ADD(Channel) | \
SPI_AD7908_PM(3) | \
SPI_AD7908_SEQ(0) | \
SPI_AD7908_SHADOW(0) | \
SPI_AD7908_RANGE(0) | \
SPI_AD7908_CODING(1);
else //read
dat_16 = SPI_AD7908_WRITE(writeread) | \
SPI_AD7908_ADD(Channel) | \
SPI_AD7908_PM(3) | \
SPI_AD7908_SEQ(0) | \
SPI_AD7908_SHADOW(0) | \
SPI_AD7908_RANGE(0) | \
SPI_AD7908_CODING(1);
dat_16 <<= 4;
return dat_16;
}
uint16_t SPI_ReadWrite(uint16_t TxData)
{
uint16_t RxData = 0;
int i = 0;
AD7908_CS = 0;
delay_us(1);
for (i = 0; i < 16; i++)
{
AD7908_MOSI = (TxData & 0x8000) ? 1 : 0;
delay_us(1);
AD7908_CLK = 0;
delay_us(1);
RxData <<= 1;
TxData <<= 1;
AD7908_CLK = 1;
delay_us(1);
RxData |= AD7908_MISO;
}
delay_us(1);
AD7908_CLK = 1;
AD7908_CS = 1;
return RxData >> 1;
}
循环体:
addr++;
if (addr > 7) addr = 0;
AD7908_Recive = SPI_ReadWrite(SPI_AD7908_Write_Control(1, addr));
printf("%d:%x %d\r\n", addr, AD7908_Recive, (AD7908_Recive >> 4) & 0xFF);
delay_ms(1000);
看一下输出结果,IN4连接的3.3V,量程为5V,5/255*168=3.294V完美。
1:22a0 42
2:12d0 45
3:2370 55
4:34a0 74
5:4a80 168
6:56c0 108
7:6530 83
0:7480 72
1:380 56
2:1350 53
3:2360 54
4:34c0 76
5:4a80 168
6:5700 112
7:6550 85
0:7490 73
注意,每次返回的结果都是上次写入参数时读取的结果!