MCP41010芯片介绍
MCP41010芯片封装图
1号脚,片选信号角,在上电以后,该引脚上施加低电平时才可以对芯片内部数据进行写入
2号脚,时钟信号脚,在对芯片进行数据写入时,需要给其提供时钟信号,例如在本次实验中写入数据时就要在该引脚上产生16个连续的脉冲。
3号脚,数据脚,这个引脚会接收控制器发出的串行信号。
4号脚,GND,这个引脚用来接地。
8号脚,Vdd,这个引脚用来接电源线,根据其数据手册可以提供2.7V到5.5V的电压。
5、6、7号脚,时芯片内部的电位计。
在这个电位计上有256(2^8)个抽头位置,PW0的具体位置将由写入的数据决定。当写入数据为0,PW0将移动到PB0的位置,若写入255则PW0将移动到PA0的位置。
控制器向芯片写入数据时要发送两个字节的串行数据,其中第一个字节用来选择工作状态,其中只有C1、C0、P1、P0这四位需要关注。
根据数据手册的内容,本实验使用写入数据操控Potentiometer0,所以向芯片发送的第一个字节的数据为00010001。
还有两个需要注意的点是,在对芯片进行数据写入时需要对片选信号置于低电平且在数据传输结束以后,需要将片选信号拉高。MCP41010芯片对数据线的信号采样发生在SCK的上升沿。
SPI总线通讯
SPI 是由摩托罗拉(Motorola)公司开发的全双工同步串行总线,是微处理控制单元(MCU)和外围设备之间进行通信的同步串行端口。主要应用在EEPROM、Flash、实时时钟(RTC)、数模转换器(ADC)、网络控制器、MCU、数字信号处理器(DSP)以及数字信号解码器之间。SPI 系统可直接与各个厂家生产的多种标准外围器件直接接口,一般使用4 条线:串行时钟线SCK、主机输入/从机输出数据线MISO、主机输出/从机输入数据线MOSI 和低电平有效的从机选择线SSEL。
SPI多数情况下用做在主机与从机之间的通讯,本实验中则利用单片机中的SPI模块对MCP41010芯片进行数据写入。
在本实验使用的单片机中有以下寄存器与SPI通讯的设置相关
SPCTL是SPI控制寄存器,其中最高位SSIG用来控制单片机引脚的工作状态,确定该单片机为从机还是主机。SPEN是使能位,只有改为为1时才会使得单片机工作在SPI的模式下。
DORD用来设置数据发送的顺序(1,LSD(最低位)先发送,0,MSB(最高位)先发送)。CPOL用来控制输出的时钟端空闲时的高低电平。CPHA用来选择数据与时钟的配合模式。
本人在实验中选取了CPOL=1;CPHA=0的工作方式,下图为该工作方式下产生的脉冲,红色箭头为采样的位置。
最后两位SPR1与SPR0则是用于选择SPI时钟的速率(可以类比于设置51系列串行通讯的bode率)
SPSTAT寄存器是用于描述SPI通讯的,其中SPIF为通讯结束的标志位,当一次通讯结束后SPIF会置1,需要软件对其进行清0(类比于51单片机串行通讯的标志位TI)WCOL位为写冲突。
SPDAT寄存器用于存放将要进行SPI通讯的数据,在控制寄存器允许的情况下,写入SPDAT以后就会进行通讯(就好比51中的SBUF)
AUXR1寄存器可以将默认的P1口实现SPI功能移动到P4口上;由于本实验中没有使用到该寄存器不作介绍。(不过该寄存器中ADRJ位是设置10位AD转换后数据存放模式的一位在实验4中会用到)
下图为数据手册提供的工作模式选择表
本实验中选择了最下面这一列的工作模式
电路设计图
IO口模拟SPI代码 |
#include<reg52.h> #define uchar unsigned char #define uint unsigned int sbit CS=P1^4; sbit SCLK=P1^7; sbit MOSI=P1^5; uchar num1[8]={0,0,0,1,0,0,0,1}; //0X11 uchar num3[8]={0,1,0,0,1,1,0,0}; //0x4C uchar num8[8]={1,1,0,0,1,1,0,0}; //0XCC uchar count,flag; void send(uchar num[8]); void delay(uchar j) //延时函数 { uchar i; i=125; for(;j>0;j--) { while(i--) { ; } } } void main() {
TR0=0; TMOD=0x01; //设置定时器为方式1 16位 并且工作于计时状态 TH0=0x3c; //目标间隔5秒,晶振位4M,一个机器周期3us //让定时器计时0.15s再由i计数33次 //(2^16-50000)为TH0与TL0中值 TL0=0xb0; EA=1; //开总中断 ET0=1; //开定时器T0中断 count=33; while(1) { flag=1; send(num3); TR0=1; while(flag); //while(flag)用来等待计时满5s //计时满5s以后会将flag=0,并且关闭定时器
flag=1; send(num8); TR0=1; while(flag);
} } void timer0() interrupt 1 //中断函数因为使用定时器T0 //所以中断号为1 { TH0=0x3c; TL0=0xb0; count--; if(count<=0) { flag=0; count=33; TR0=0; } } void send(uchar num[8]) //用来产生16个脉冲并发送模式信号与数据信号 { uchar t; CS=1; SCLK=0; delay(5); CS=0; //低电平允许写入 delay(2); for (t=0;t<8;t++) //发送状态 { MOSI=num1[t]; delay(2); SCLK=1; delay(2); SCLK=0; } for (t=0;t<8;t++) //发送数据 { MOSI=num[t]; delay(2); SCLK=1; delay(2); SCLK=0; } delay(2); CS=1; //高电平结束写入状态 } |
为了保证实验的顺利进行,本人用模拟spi程序利用proteus上的51单片机模型进行了波形时序的论证 |
调用单片机SPI模块 |
#include<reg52.h> #define uchar unsigned char #define uint unsigned int sfr SPCTL=0xce; sfr SPSTAT=0xcd; sfr SPDAT=0xcf; sbit CS=P1^4; sbit SCLK=P1^7; sbit MOSI=P1^5; uchar flag,count; void delay(uchar j) { uchar i; i=125; for(;j>0;j--) { while(i--) { ; } } } void main() { TR0=0; TMOD=0x01; //设置定时器为方式1 16位 并且工作于计时状态 TH0=0x3c; //目标间隔5秒,晶振位4M,一个机器周期3us //让定时器计时0.15s再由i计数33次 //(2^16-50000)为TH0与TL0中值 TL0=0xb0; EA=1; //开总中断 ET0=1; //开定时器T0中断 count=33; SPCTL=0xfc; MOSI=1; flag=0;
while(1) { while(flag); CS=0; delay(200); SPDAT=0X11; //写入数据进行发送 while((SPSTAT&0x80)==0); //等待SPI发送完成 SPSTAT=0x00; SPDAT=0x4c; while((SPSTAT&0x80)==0); SPSTAT=0x00; CS=1; flag=1; TR0=1;
while(flag); CS=0; delay(1); SPDAT=0x11; while((SPSTAT&0x80)==0); SPSTAT=0x00; SPDAT=0xcc; while((SPSTAT&0x80)==0); SPSTAT=0x00; CS=1; flag=1; TR0=1; } } void timer0() interrupt 1 //中断函数因为使用定时器T0 //所以中断号为1 { TH0=0x3c; TL0=0xb0; count--; if(count<=0) { flag=0; count=33; TR0=0; } } |
该程序的框图 |
实验现象
增益为-3.31 |
增益为-4.95 |
关于实验结果与理论值差异的说明!
在实验中得到了实验现象,发现该增益在-3与-5左右变化。这与设计的增益有着很大的差异,在后续的复盘中我发现自己将数字电位计的PWB引脚错误的接到了PWA引脚上,导致输入的电阻为2与7。根据反相比例放大电路增益公式,得到的结果符合这对阻值。