MSP430------2

本文详细介绍了MSP430单片机的COMPARE模块和ADC10模块的工作原理及应用,并提供了IIC通信接口的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里首先补充下IO口的中断,中断是通过PxIE,PxIES,PxIFG决定的,配置中断仍然要设置方向寄存器,上拉下拉使能寄存器,上拉下拉极性寄存器。


在这块芯片中有个COMPARE模块,这个模块就是个比较器而已。如图1.



图1 compare的结构图

这张图清楚表明了compare的结构和控制的方法。

作为一个比较器的话,首先要有同向输入端和反向输入端,同向输入端是通过CA0,CA1,CA2三位决定的,如果是000代表的是内部输入!剩下的那部分就是内部参考电压选择,CAEX是交换输入端,这样的话就会使输出CAOUT反转,CARSEL就是选择输入到参考电压输入到哪个端子,CAON是比较器是否打开,CAOUT是输出的值,这个不是管脚而是寄存器的值,CAF是输出滤波的禁用和使能控制端。程序如下:

void compare_init(void)
{
  CACTL1 = 0x00;
  CACTL2 = 0x00;
  //CAPA = 0x00;
  
  /* 选择参考电压为0.25V */
  CACTL1_bit.CAREF1 = 0;
  CACTL1_bit.CAREF0 = 1;
  
  CACTL2 |= (4<<3);
  
  CACTL2_bit.CAF = 1;
  
  CACTL1_bit.CAON = 1;
  
}

注意:大家可以直接把这个模块理解为一个集成在MSP430内部的比较器,里面的控制器就是你要接的线的控制开关。画张比较器的图一一对比就比较好理解其功能了。



ADC10模块:

在这块芯片中有个ADC模块而且有四种模式,单通道单次,单通道连续,序列单次,序列连续,这里解释几个名词,什么是通道呢?直观上讲,我们配置好ADC后,每个管脚就是通道了;什么是序列?序列我说个简单的理解方式,就是一个通道就是包含一个元素的序列,多个通道就是一个多个元素的序列了;但是序列是怎么组织呢?在MSP430中序列的意思就是,从你要开始采集的通道开始,一个接一个的采集直道通道0,举个例子就是如果我们配置的是从通道4开始,那么它会转化完通道4接着转化通道3接着是通道2接着通道1接着通道0,这时如果设置的是单次那么就不转化了,如果是连续的话,它就会再次从通道4开始直到通道0转化结束,周而复始转化。同样我们学习ADC就要开他的结构图了,如图2。



图2

ADC转换需要参考电压,时钟,输入信号;我们就以这几个开始说明工作原理,再贴程序,参考电压是在上面的那块。

参考电压是通过内置的,为了适应不同环境,那么就有多个参考了,这时就要有选择的寄存器位了,因为只有两个就通过一个位来的REF_2.5(这里还有个附加功能就是输出这个参考电压,这是通过REFOUT位设置的,输出的方式又通过REFBURST实现是连续还是只在采样时输出,当然还需要设置IO口的功能了,一般用不到这里就不说了),有了这些后,我们到底是选择最小,最大参考电压呢?这些SREF[0:3]设置的(这三位在寄存器ADC10CTL0的15-13位)。

AD转化是需要时间的所以要有采样保持位通过ADC10SHTX[0:1](ADC10CTL0寄存器的12-12位),时钟是通过SHSX选择的,这张图里面的同步sync是不存在的,MSP430只有ENC控制使能和禁止位,时钟分频因子,好了配置好之后ADC10的时钟ADC10CLK就确定了。

输入信号,就是配置IO输入引脚了,这些就是通过ADC10AEx选择的,这时候的IO口就是AD输入了,大家可以看看上篇的管脚第二功能选择。


为了存下ADC10的数据呢,就需要一个寄存器保存这个值,这个模块中设计了一个ADC10MEM,这个就是数据的读取地方,具体就是当结果转化完ADC10模块就把数据放到这个寄存器中,但我们什么时候知道数据完成了呢?又需要一个标志位了,这个标志位就是ADC10IFG,这里提一下这个模块还提供了一个ADC10BUSY位用指示模块是否在转化,我们开始通过开始后检查这个位来读取,不过这个方法不大好,还是通过判断ADC10IFG比较好。


为了更好的控制ADC10就要有不同的模式了,也就是上面说的四种模式了,还有中断什么的,这些都和以前说的中断一样,打开中断使能。

程序如下

void ad10_scsc_init(unsigned char channel)
{
  ADC10CTL0 |= (1<<13)|(2<<11)|(1<<6)|(1<<5)|(1<<3);
  ADC10CTL1 |= (channel<<12)|(7<<5)|(3<<3);
  ADC10AE0 |= (1<<0);
  ADC10CTL0 |= (1<<4);
}

void ad10_start(void)
{
  ADC10CTL0 |=(3<<0);
}

void ad10_scsc_read(unsigned short *ad_date)
{
  while(ADC10CTL1&(1<<0));
  *ad_date=ADC10MEM;
}

注意:这是个单通道单次的,也是我们经常使用的,因为初始化时一定不要打开转化,因为数据可能不是我们要的,我们需要在我们需要时再转化,转化是要在一条语句中置位ENC,ADC10SC,具体的原因就是设计这个模块的人知道了,呵呵,文档是怎么说的。这个是中断接受的程序,所以我没判断ADC10IFG,因为进中断肯定是ADC10IFG置位了,所以就没必要判断了。

好了,到此为止,ADC就介绍完了,这个芯片就差SPI模块了,但是这个模块不好使,觉得你还是自己模拟下时序吧,我模拟了一个IIC的希望对大家有益,下面我把IIC的程序贴上,这是验证过的,具体的IIC协议在下一篇文档中介绍下,并且说点书电知识。

#include "iic.h"
#include "io430.h"
#include "delay.h"


unsigned char g_iic_date;


#define IIC_CLK P1OUT_bit.P7
#define IIC_W_SDA P1OUT_bit.P6
#define IIC_R_SDA P1IN_bit.P6


void iic_reset(void)
{
  P1OUT_bit.P6 = 0;
  P1OUT_bit.P7 = 0;
  P1DIR_bit.P6 = 0;
  P1DIR_bit.P7 = 0;
  P1REN_bit.P6 = 0;
  P1REN_bit.P7 = 0;
  P1SEL_bit.P6 = 0;
  P1SEL_bit.P6 = 0;
  P1SEL_bit.P7 = 0;
  P1SEL2_bit.P6 = 0;
  P1SEL2_bit.P7 = 0;
}


void iic_clk_init(void)
{
  P1DIR_bit.P7 = 1;
  P1OUT_bit.P7 = 0;
}


void iic_w_sda_init(void)
{
  P1REN_bit.P6 = 0;
  P1DIR_bit.P6 = 1;
  P1OUT_bit.P6 = 1;


}


void iic_r_sda_init(void)
{
  P1DIR_bit.P6 = 0;
  P1REN_bit.P6 = 1;  
  P1OUT_bit.P6 = 1;
}


void iic_start(void)
{
  IIC_CLK = 1;
  delay(1);
  IIC_W_SDA = 1;
  delay(1);
  IIC_W_SDA = 0;
  delay(1);
}


void iic_send_date(unsigned char iic_byte)
{
  unsigned char i_temp;
  for(i_temp=0;i_temp<8;i_temp++)
  {
    IIC_CLK = 0;
    delay(1);
    if((iic_byte>>(7-i_temp))&0x01)
    {
      IIC_W_SDA = 1;
    }
    else
    {
      IIC_W_SDA = 0;
    }
    delay(1);
    IIC_CLK = 1;
    delay(1);
  }
  IIC_CLK=0;
  delay(1);
}


void iic_read_date(unsigned char *iic_r_byte)
{
  unsigned char i_temp;
  unsigned char date_temp;
  IIC_CLK=0;
  ;;;;;;;
  for(i_temp=0;i_temp<8;i_temp++)
  {
    IIC_CLK = 0;
    delay(1);
    IIC_CLK = 1;
    delay(1);
    if(IIC_R_SDA!=0)
      date_temp |= 1<<(7-i_temp);
    else
      date_temp |= 0<<(7-i_temp);
    delay(1);
  }
  *iic_r_byte=date_temp;
  IIC_CLK = 0;
  delay(1);
}


void iic_response(void)
{
  unsigned char i_temp=0;
  IIC_CLK = 0;
  delay(1);
  IIC_CLK = 1;
  delay(1);
  while((IIC_R_SDA!=0)&&(i_temp<255))i_temp++;
  IIC_CLK = 0;
  delay(1);


}


void iic_stop(void)
{
  IIC_W_SDA = 0;
  delay(1);
  IIC_CLK = 1;
  delay(1);
  IIC_W_SDA = 1;
  delay(1);
  IIC_CLK = 0;
  delay(1);
}


void iic_start_write(void)
{
  iic_clk_init();
  delay(1);
  iic_w_sda_init();
  iic_start();
  iic_send_date(0xa0);
  iic_r_sda_init();
  delay(1);
  iic_response();
  
  iic_w_sda_init();
  iic_send_date(0xa0);
  iic_r_sda_init();
  delay(1);
  iic_response();
  
  iic_w_sda_init();
  iic_send_date(0xa0);
  iic_r_sda_init();
  delay(1);
  iic_response();
  
  iic_w_sda_init();
  iic_stop();
    
}


void iic_start_read(void)
{
  iic_w_sda_init();
  iic_start();
  iic_send_date(0xa0);
  iic_r_sda_init();
  delay(1);
  iic_response();


  iic_w_sda_init();
  iic_send_date(0xa0);
  iic_r_sda_init();
  delay(1);
  iic_response();
  
  iic_w_sda_init();
  iic_start();
  iic_send_date(0xa1);
  iic_r_sda_init();
  delay(1);
  iic_response();
  
  iic_read_date(&g_iic_date);
  delay(1);
  iic_w_sda_init();
  iic_stop();
}



好了MSP430到此为止了,学习这块芯片我用了四天,其实只要有好的单片机基础完全可以学的很快,而且理解也很深的噢,这里也随便说说我读文档时理解的一个小知识点,这块芯片是统一寻址的,也就是寄存器和存储单元是统一编址的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值