2010-12-24 14:38:00 wenxing462 阅读数 1289
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4000 人正在学习 去看看 朱有鹏

本系统设计利用单片机实现温度数据采集与传输;计算机实现温度数据的接收、分析及处理的一种设计方法,应用于近距离温度检测。主要涵盖了传感器、计算机串口通信、C程序及VB编程、单片机和计算机信息处理等几方面技术。

本系统硬件电路主要采用温度传感器DS18B20、液晶显示器1602及单片机STC89C52。传感器将所测的温度转换为电信号,由单片机进行采集并进行ASCII编码,为液晶显示及串行口通信作准备。根据串行通信原理,采用新型电平转换芯片MAX232实现TTL电平与RS-232电平双向转换,建立了单片机与计算机之间通信。利用VB6.0编程实现将采集到的温度数据的接收、分析和存储,将温度数据显示在计算机窗口中并绘制温度的实时曲线,同时在必要的时候可以通过电子邮件的方式将系统状态发送给用户以便于用户进行分析和远程实时操作。     

更多内容请联系:QQ544921189

2013-01-26 21:39:52 h32dong809 阅读数 4110
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4000 人正在学习 去看看 朱有鹏

 怎么上传图片呀?

 

1.系统简介

     本系统为xxx检测仪,用于检测xxx载重量,并以模拟输出量形式把载重量传递给主控制系统。

     检测仪根据电梯轿底橡胶块随载重做弹性变化的原理,通过霍尔传感器检测其位移变化且把相应的位移变化变化为电压信号,把传感器传输过来的电压信号经过PIC内部的10位A/D转换为数字信号,单片机把采集到数字量数据经过一系列复杂浮点运算处理后,通过PIC内部PWM模块实现D/A转换。把单片机处理后的数字量数据转换为模拟量数据输出(0.5V—3.5V)。      

 

2.方案选择

(1)      主控制芯片。

      主控制芯片选用PIC单片机,PIC单片机MicroChip单片机的主要产品是PIC 16C系列和17C系列8位单片机,相对于51系列单片机,PIC单片机CPU采用RISC结构,分别仅有33,35,58条指令,采用Harvard双总线结构,运行速度快,低工作电压,低功耗,较大的输入输出直接驱动能力,价格低,一次性编程,小体积. 适用于用量大,档次低,价格敏感的产品.在办公自动化设备,消费电子产品,电讯通信,智能仪器仪表,汽车电子,金融电子,工业控制不同领域都有广泛的应用,PIC系列单片机在世界单片机市场份额排名中逐年提高.发展非常迅速。.

(2)      A/D转换电路

PIC单片机内带A/D转换电路。采用PIC内带A/D转换电路省去了专用A/D转换芯片,降低成本,再者PIC内带A/D转换精度达到10BIT。满足实际生产精度要求。

(3)      D/A转换电路

实现D/A转换有很多种方法,例如采用D/A转换器,F/V频率电压转换器,加权电阻或R-2R的梯形电阻网络均可以实现,本设计才用PIC单片机的PWM脉宽调制器可以实现模数转换。具有电路简单,成本低的特点。同时通过完善后续RC滤波电路,可以实现高精度的输出,满足实际生产需求。

(4)      总结

总的来说,本设计充分利用了PIC单片机内部资源,电路简单,功能齐备,成本低。

 

3.电路设计

(5)       A/D转换电路。

数字系统只能处理数字信号,而称重传感器输出电压量是模拟信号,若要在数字系统中处理这些信号,则必须先把传感器测量的模拟量通过A/D转换模块将其转换为数字量。PIC内部A/D转换一般包括4个步骤,即采样,保持,量化,编码。

A/D转换电路输入如下图1所示:

 

图 1   A/D转换输入电路


     

 图中Vi即是传感器测量的模拟量输入口,二极管的作用的防止反流,起保护作用。

(因R18的电阻值极大,分流极小可忽略不计,故输入到单片机A/D转换口RA0的电压值约为Vi值。保护电路对输入值影响不大)。

(2) 按键电路

按键盘电路电路图如下图2所示:

图中电阻,电容作用是用于去除按键抖动。当按键未被按下时,对应的IO口为高电平,当按键被按下时,IO口高电平被拉低,单片机获得此信息,进而跳转到相应程序执行。

图2   按键电路

 

(6)       D/A转换电路

D/A转换电路电路图如下图3所示:

      其中R11,C6构成RC滤波电路,用于实现PWM波转直流,LM358用作电压跟随器,以提高输出电路的带负载能力。

      D/A转换输出Vout=Vcc*(PWM高电平值/PWM周期值)=5*脉宽/(PR2+1)。

      其中Vout=3.5-3*(Vin-Vmin)/(Vmax-Vmin)

      (其中Vin是传感器输入值,Vmin是满载自学习值,Vmax是满载自学值)

 

图 3   D/A转换电路电路图

 

(7)       电源电路

电源电路电路图如下图4所示:

       24V 输入电压进78M12后转变为12V电压输出为LM358提供电源,12V电压输入到7805后输出5V电压,供单片机及其他芯片用电。电路中的电容起滤波稳压作用。

 

                                图 3  电源电路图

2018-07-12 19:15:13 weixin_41695564 阅读数 1178
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4000 人正在学习 去看看 朱有鹏

      本文利用 MC9S12XEP100 单片机来学习A/D采集功能。

      首先开发板上有两个电位计作为A/D采集的输入信号,拉下图所示:


  将采集到的信号作比较,利用判断结果来控制开发板上的二极管的开和灭,二极管的电路连接如下:


然后将AD0的转换后的结果采用扫描的方式输出在数码管上,数码管的电路原理图如下:

    数码管的每个阳极连接一个限流电阻,8个阳极和单片机的PP0~PP7引脚相连。数码管的四个阴极采用4个三极管作为开关。三极管的基极经过电阻之后与单片机的PK3~PK0引脚相连。按照这个电路,扫描的具体方法是:P口输出第一位数码的码段,  K口控制第一位导通而其他三位不导通,延时5ms后,P口输出第二位数码的码段,  K口控制第二位导通而其他三位不导通,如此直到扫描完第四位后,继续扫描第一位。

     在code warrior中程序源代码如下所示:

#include <hidef.h>      /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */

#define  BUS_CLOCK		   40000000	     //总线频率,改变总线频率直接在此处修改
#define  OSC_CLOCK		   16000000	     //晶振频率
#define LEDCPU PORTK_PK4
#define LEDCPU_dir DDRK_DDRK4


#define CONT1 PORTK_PK3
#define CONT2 PORTK_PK2
#define CONT3 PORTK_PK1
#define CONT4 PORTK_PK0
#define CONT1_dir DDRK_DDRK3
#define CONT2_dir DDRK_DDRK2
#define CONT3_dir DDRK_DDRK1
#define CONT4_dir DDRK_DDRK0 
#define DATA PTP
#define DATA_dir DDRP

unsigned char AD_in0,AD_in1;


byte data1 = 0;
byte data2 = 0;
byte data3 = 0;
byte data4 = 0;
byte single = 1;

byte shuma[20]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,       //0~9对应的段码
                0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};      //0~9后加小数点对应的段码
                
    
                

/* ------------------------------------------------------------------------------------
// ATD 的运行方式分为单次和连续运行两种:
//     在单次方式下,每个转换序列完成后,寄存器 ATDSTAT 中的 SCF 置位,然后 ATD 模块暂停。
//     在连续方式下,转换以转换序列为单位连续进行,当第一个转换序列完成后,SCF 置位,
//     同时 ATD 模块开始下一个转换序列。
//  在上述两种方式下,每个通道的转换结果进入到对应结果寄存器后,寄存器ATDSTAT1中对应的 CCF 位置 1,
//  对存放转换结果的寄存器进行读操作后,CCF 位将自动清0.
//  转换过程的启动是通过写入寄存器 ATDCTL5 实现的。
//  ATD 转换所需要的时钟周期数是固定不变的,但是采样时间和时钟频率可以通过 ATDCTL4 在一定范围内选择.
//  因此转换时间也可以选择。
// ---------------------------------------------------------------------------------- */

/*--------------------------------------------------------------------------------------
// MCU上电后, ATD模块各个寄存器处于默认关闭状态, 至少需要经过下面几个步骤, 才可以使ATD完成
// 所需要的转换工作:
//  (1) 设置ATD 控制寄存器 ATDCTL1-4: 根据对转换位数、扫描方式、采样时间、时钟频率的要求及
//  标志检查方式进行相应寄存器的设置; 
//  (2) 通过写ATD 控制寄存器 ATDCTL5 启动新的ATD转换.
//  (3) 通过查询ATD 状态寄存器 ATDSTAT0 或响应A/D转换完成标志做中断处理.
// ------------------------------------------------------------------------------------*/





/*************************************************************/
/*                      初始化锁相环                         */
/*************************************************************/
void INIT_PLL(void) 
{
    CLKSEL &= 0x7f;       //设置OSCCLK作为系统时钟
    PLLCTL &= 0x8F;       //禁止锁相环
 
    //PLLCLK=2×OSCCLK×(SYNR+1)/(REFDV+1), fbus=PLLCLK/2
    #if(BUS_CLOCK == 120000000) 
        SYNR = 0xcd;
    #elif(BUS_CLOCK == 104000000) 
      SYNR = 0xcc;
    #elif(BUS_CLOCK == 96000000)                      
      SYNR = 0xcb;
    #elif(BUS_CLOCK == 88000000) 
      SYNR = 0xca;
    #elif(BUS_CLOCK == 80000000) 
      SYNR = 0xc9;
    #elif(BUS_CLOCK == 72000000) 
      SYNR = 0xc8;
    #elif(BUS_CLOCK == 64000000) 
      SYNR = 0xc7;
    #elif(BUS_CLOCK == 56000000) 
      SYNR = 0xc6;
    #elif(BUS_CLOCK == 48000000) 
      SYNR = 0xc5;
    #elif(BUS_CLOCK == 40000000) 
      SYNR = 0x44;
    #elif(BUS_CLOCK == 32000000)
      SYNR = 0x43;     
    #elif(BUS_CLOCK == 24000000)
      SYNR = 0x42;
    #elif(BUS_CLOCK == 16000000)
      SYNR = 0x01;
   #endif 

    REFDV = 0x81;
    PLLCTL |=0x70;  //使能锁相环
    asm NOP;
    asm NOP;
    while(!(CRGFLG&0x08)); //PLLCLK锁定
    CLKSEL |= 0x80;        //设置PLLCLK为系统时钟
}






/*************************************************************/
/*                      初始化AD模块                         */
/*************************************************************/  
     
void INIT_AD(void)

{

  ATD0DIEN_IEN0 = 0;
  ATD0DIEN_IEN1 = 0;
  
 // 相应AD通道禁止为I/O口 
 // ATD0DIEN 是ATD 数字信号输入使能寄存器,
 //     0: 禁止数字信号输入
 //     1: 允许数字信号输入
 
  
  ATD0CTL2 = 0x40;   
       
  // 启动A/D转换,快速清零,禁止中断
  // ATD0CTL2 的定义如下:
  /*
    // ATD0CTL2 - ATD 0 Control Register 2; 0x000002C2 
    union {
      byte Byte;
      struct {
        byte ACMPIE      :1;             // ATD Compare Interrupt Enable  
        byte ASCIE       :1;             // ATD Sequence Complete Interrupt Enable  
        byte ETRIGE      :1;             // External Trigger Mode enable  
        byte ETRIGP      :1;             // External Trigger Polarity  
        byte ETRIGLE     :1;             // External Trigger Level/Edge control  
        byte ICLKSTP     :1;             // Internal Clock in Stop Mode Bit  
        byte AFFC        :1;             // ATD Fast Conversion Complete Flag Clear  
        byte             :1; 
      } Bits;
    } ATD0CTL2STR;
    #define ATD0CTL2                    _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Byte
    #define ATD0CTL2_ACMPIE             _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.ACMPIE
    #define ATD0CTL2_ASCIE              _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.ASCIE
    #define ATD0CTL2_ETRIGE             _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.ETRIGE
    #define ATD0CTL2_ETRIGP             _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.ETRIGP
    #define ATD0CTL2_ETRIGLE            _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.ETRIGLE
    #define ATD0CTL2_ICLKSTP            _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.ICLKSTP
    #define ATD0CTL2_AFFC               _ATD0CTL23.Overlap_STR.ATD0CTL2STR.Bits.AFFC
  */ 
 
   // ATD0CTL2寄存器如下:
   //  ________________________________________________________________
   // |      |       |       |       |       |        |       |        |
   // |      |  AFFC |ICLKSTP|ETRIGLE| ETRIGP| ETRIGE | ASCIE | ACMPIE |
   // |______|_______|_______|_______|_______|________|_______|________|
   
   // AFFC ------ A/D快速转换完成标志位清零
   //      1: 快速标志位清零顺序, 每次读取结果寄存器自动清零
   //      0: 正常标志位清零顺序, 需要手动对状态标志位清零
   // 
   
 
 
  ATD0CTL1_SRES = 0b00; 
      
  // ATD转换精度设置为8位
  // 我们进入头文件查看 ATD0CTL1_SRES 的定义:                          
   /*
       // ATD0CTL1 - ATD 0 Control Register 1; 0x000002C1
       struct {
       union {
          byte Byte;
          struct {
            byte ETRIGCH0    :1;            // External Trigger Channel Select Bit 0 
            byte ETRIGCH1    :1;            // External Trigger Channel Select Bit 1  
            byte ETRIGCH2    :1;            // External Trigger Channel Select Bit 2  
            byte ETRIGCH3    :1;            // External Trigger Channel Select Bit 3  
            byte SMP_DIS     :1;            // Discharge Before Sampling Bit  
            byte SRES0       :1;            // A/D Resolution Select Bit 0  
            byte SRES1       :1;            // A/D Resolution Select Bit 1  
            byte ETRIGSEL    :1;            // External Trigger Source Select  
                 } Bits;
          struct {
            byte grpETRIGCH :4;
            byte     :1;
            byte grpSRES :2;
            byte     :1;
                  } MergedBits;
               } ATD0CTL1STR;    
             } Overlap_STR;
           } ATD0CTL01STR;
   
        extern volatile ATD0CTL01STR _ATD0CTL01 @(REG_BASE + 0x000002C0UL);
        #define ATD0CTL1                    _ATD0CTL01.Overlap_STR.ATD0CTL1STR.Byte
        #define ATD0CTL1_SRES               _ATD0CTL01.Overlap_STR.ATD0CTL1STR.MergedBits.grpSRES   
    */
  // 因此ATD0CTL1_SRES 有两个 位 的空间, 
  
 
   
  
  
  ATD0CTL3 = 0x90;        
  
  // 转换序列长度为2,右对齐模式
  /*
    // ATD0CTL3 - ATD 0 Control Register 3; 0x000002C3  
    union {
      byte Byte;
      struct {
        byte FRZ0        :1;           // Background Debug Freeze Enable Bit 0  
        byte FRZ1        :1;           // Background Debug Freeze Enable Bit 1  
        byte FIFO        :1;           // Result Register FIFO Mode  
        byte S1C         :1;           // Conversion Sequence Length 1 
        byte S2C         :1;           // Conversion Sequence Length 2  
        byte S4C         :1;           // Conversion Sequence Length 4  
        byte S8C         :1;           // Conversion Sequence Length 8  
        byte DJM         :1;           // Result Register Data Justification  
      } Bits;
      struct {
        byte grpFRZ :2;
        byte     :1;
        byte     :1;
        byte     :1;
        byte     :1;
        byte     :1;
        byte     :1;
      } MergedBits;
    } ATD0CTL3STR;
    #define ATD0CTL3                    _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Byte
    #define ATD0CTL3_FRZ0               _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.FRZ0
    #define ATD0CTL3_FRZ1               _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.FRZ1
    #define ATD0CTL3_FIFO               _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.FIFO
    #define ATD0CTL3_S1C                _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.S1C
    #define ATD0CTL3_S2C                _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.S2C
    #define ATD0CTL3_S4C                _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.S4C
    #define ATD0CTL3_S8C                _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.S8C
    #define ATD0CTL3_DJM                _ATD0CTL23.Overlap_STR.ATD0CTL3STR.Bits.DJM
    #define ATD0CTL3_FRZ                _ATD0CTL23.Overlap_STR.ATD0CTL3STR.MergedBits.grpFRZ
  */                 
   // ATD0CTL3(ATD控制寄存器3)如下所示:
  
   //bit  7      6        5      4       3       2        1       0
   //  ________________________________________________________________
   // |      |       |       |       |       |        |       |        |
   // | DJM  |  S8C  |  S4C  |  S2C  |  S1C  | FIFO   |  FRZ1 | FRZ0   |
   // |______|_______|_______|_______|_______|________|_______|________|
   //
   // (1) DJM  ----- 结果寄存器数据对齐方式
   //    这一位决定结果寄存器的数据如何向IP数据总线的位上映射.映射关系取决于A/D转换的分辨率。
   //    对于10位的分辨率, 左对齐模式下,结果寄存器数据将映射到数据总线的6~15位, 第15位为高位; 
   //                      右对齐模式下,结果寄存器数据将映射到数据总线的0~9位,第9位为高位.
   //    对于8位的分辨率,  左对齐模式下,结果寄存器数据将映射到数据总线的8~15位, 第15位为高位; 
   //                      右对齐模式下,结果寄存器数据将映射到数据总线的0~7位,第7位为高位.
   //    0: 左对齐模式
   //    1: 右对齐模式
   //
   // (2) S8C/S4C/S2C/S1C ----- 选择转换序列的长度
  
  
  
  
 
  ATD0CTL4 = 0x84;
         
  // 采样时间为12个ATD转换时钟周期数, 
  // fatdclk = fbus/(2*(prs+1))=40/2/5, 
  // 因此 AD模块时钟频率为4MHz         
  
  // 首先ATD0CTL4 在头文件中的定义为:  
  /*  
   struct {
    // ATD0CTL4 - ATD 0 Control Register 4; 0x000002C4  
    union {
      byte Byte;
      struct {
        byte PRS0        :1;       // ATD Clock Prescaler 0 
        byte PRS1        :1;       // ATD Clock Prescaler 1 
        byte PRS2        :1;       // ATD Clock Prescaler 2 
        byte PRS3        :1;       // ATD Clock Prescaler 3 
        byte PRS4        :1;       // ATD Clock Prescaler 4 
        byte SMP0        :1;       // Sample Time Select 0 
        byte SMP1        :1;       // Sample Time Select 1 
        byte SMP2        :1;       // Sample Time Select 2 
      } Bits;
      struct {
        byte grpPRS :5;
        byte grpSMP :3;
      } MergedBits;
    } ATD0CTL4STR;
    #define ATD0CTL4                    _ATD0CTL45.Overlap_STR.ATD0CTL4STR.Byte
    #define ATD0CTL4_PRS0               _ATD0CTL45.Overlap_STR.ATD0CTL4STR.Bits.PRS0
    #define ATD0CTL4_PRS1               _ATD0CTL45.Overlap_STR.ATD0CTL4STR.Bits.PRS1
    #define ATD0CTL4_PRS2               _ATD0CTL45.Overlap_STR.ATD0CTL4STR.Bits.PRS2
    #define ATD0CTL4_PRS3               _ATD0CTL45.Overlap_STR.ATD0CTL4STR.Bits.PRS3
    #define ATD0CTL4_PRS4               _ATD0CTL45.Overlap_STR.ATD0CTL4STR.Bits.PRS4
    #define ATD0CTL4_SMP0               _ATD0CTL45.Overlap_STR.ATD0CTL4STR.Bits.SMP0
    #define ATD0CTL4_SMP1               _ATD0CTL45.Overlap_STR.ATD0CTL4STR.Bits.SMP1
    #define ATD0CTL4_SMP2               _ATD0CTL45.Overlap_STR.ATD0CTL4STR.Bits.SMP2
    #define ATD0CTL4_PRS                _ATD0CTL45.Overlap_STR.ATD0CTL4STR.MergedBits.grpPRS
    #define ATD0CTL4_SMP                _ATD0CTL45.Overlap_STR.ATD0CTL4STR.MergedBits.grpSMP
   */
   // ATD0CTL4(ATD控制寄存器4)如下所示:
  
   //bit  7      6        5      4       3       2        1       0
   //  ________________________________________________________________
   // |      |       |       |       |       |        |       |        |
   // | SMP2 |  SMP1 |  SMP0 |  MULT |  PRS4 | PRS3   |  PRS1 | PRS0   |
   // |______|_______|_______|_______|_______|________|_______|________|
   //
   // (1) SMP[2:0] ----- 采样时间选择
   //    这三位选择采样时间长度, 单位是ATD转换时钟周期数, SMP[2:0]取不同值对应的采样时间可以查表.
   //
   // (2) PRS[4:0] ----- ATD模块时钟的预分频系数PRS
  
   // -----------------------------------------------------------------------------    
   //  ATD时钟的计算方法如下:
   //                              fbus(总线时钟)
   //     fatdclk(ATD模块时钟) = ----------------------- 
   //                                2 * (PRS+1)
   // ---------------------------------------------------------------------------                       
}   



 

/*************************************************************/
/*                      启动AD模块                           */
/*************************************************************/ 
  
 void Start_ATD(void)
 
 {
 
   ATD0CTL5 = 0x30;    
   
   // 连续执行转换序列AN0,AN1,多通道采样模式, 从AN0通道开始采样
   // 向这个寄存器写入将中止正在执行的转换序列, 并启动一个新的转换序列. 
   
   /*
    // ATD0CTL5 - ATD 0 Control Register 5; 0x000002C5 
    union {
      byte Byte;
      struct {
        byte CA          :1;           // Analog Input Channel Select Code A 
        byte CB          :1;           // Analog Input Channel Select Code B 
        byte CC          :1;           // Analog Input Channel Select Code C 
        byte CD          :1;           // Analog Input Channel Select Code D 
        byte MULT        :1;           // Multi-Channel Sample Mode 
        byte SCAN        :1;           // Continuous Conversion Sequence Mode 
        byte SC          :1;           // Special Channel Conversion Bit 
        byte             :1; 
      } Bits;
      struct {
        byte grpCx :4;
        byte     :1;
        byte     :1;
        byte     :1;
        byte     :1;
      } MergedBits;
    } ATD0CTL5STR;
    #define ATD0CTL5                    _ATD0CTL45.Overlap_STR.ATD0CTL5STR.Byte
    #define ATD0CTL5_CA                 _ATD0CTL45.Overlap_STR.ATD0CTL5STR.Bits.CA
    #define ATD0CTL5_CB                 _ATD0CTL45.Overlap_STR.ATD0CTL5STR.Bits.CB
    #define ATD0CTL5_CC                 _ATD0CTL45.Overlap_STR.ATD0CTL5STR.Bits.CC
    #define ATD0CTL5_CD                 _ATD0CTL45.Overlap_STR.ATD0CTL5STR.Bits.CD
    #define ATD0CTL5_MULT               _ATD0CTL45.Overlap_STR.ATD0CTL5STR.Bits.MULT
    #define ATD0CTL5_SCAN               _ATD0CTL45.Overlap_STR.ATD0CTL5STR.Bits.SCAN
    #define ATD0CTL5_SC                 _ATD0CTL45.Overlap_STR.ATD0CTL5STR.Bits.SC
    #define ATD0CTL5_Cx                 _ATD0CTL45.Overlap_STR.ATD0CTL5STR.MergedBits.grpCx 
   */
   
   // ATD0CTL5(控制寄存器5)如下所示:
  
   //bit  7      6        5      4       3       2        1       0
   //  ________________________________________________________________
   // |      |       |       |       |       |        |       |        |
   // |      |  SC   |  SCAN |  MULT |   CD  |   CC   |   CB  |   CA   |
   // |______|_______|_______|_______|_______|________|_______|________|
   //
   // (1)  SC ----- 特殊通道转换使能位
   //        0: 禁止特殊通道转换
   //        1: 使能特殊通道转换
   // (2)  SCAN ---- 连续转换模式
   //        1: 连续转换模式
   //        0: 单次转换模式
   //        如果这一位为0,则一次向ATD0CTL5的写入将启动一个转换序列,转换序列被执行,
   //         执行后转换序列结束标志位(SCF)置1,之后模块返回空闲模式. 
   // (3)  MULT ----- 多通道采样模式
   //        0: 只对指定通道采样
   //        1: 对多通道采样
   // (4)  CD/CC/CB/CA ----- 模拟输入通道选择位
   //        这几位是选择哪个(或哪些)模拟输入通道的信号被采样并转换为数字信号.
   //        在通道转换模式下, 这几位表示被采样的通道
   //        在多通道转换模式下, 这几位表示转换序列的第一个通道.
   
}










/*************************************************************/
/*                      初始化周期性定时器                   */
/*************************************************************/ 
       
 void Init_PIT(void)
 
 {
  // --------------------------------------------------------------------------
  // 微处理器常常内置定时器(硬件定时器) , 比如MS9S12XS内置ECT、PWM 、以及四个24位PIT定时器
  // 想要使能某一路定时器, 需要写通道使能寄存器和 PIT 控制寄存器来使能PIT模块
  // 4个16位定时器, 共享两个8位微计数器, 通过写PIT复用寄存器来配置
  // 当某一路定时器使能时, 16位和8位计数器对应的加载寄存器的值自动加载
  // 按照MCU内部总线时钟, 24位计数器减1, 直至为零时,自动重加载,同时, 将超时标志置位, 
  // 若对应的定时中断被使能, 则产生定时中断.
  //                 (16位计数器值+1) * (8位计数器值+1)
  // 定时周期 =   ----------------------------------------- 
  //                            BusCLK
  // -------------------------------------------------------------------------------------
  
 
   PITMTLD0=249;    
   
   // 为0通道8位计数器赋值
   // PIT Micro Timer Load Register 0 to 1 (PITMTLD0-1)                 
   // 该寄存器用于设置PIT模块中的8位计数器初值,以实现24位的计数。设定值为0到255范围
   /*
   // PITMTLD0 - PIT Micro Timer Load Register 0; 0x00000346 
      typedef union {
        byte Byte;
        struct {
          byte PMTLD0      :1;                        // PIT Micro Timer Load Bit 0  
          byte PMTLD1      :1;                        // PIT Micro Timer Load Bit 1  
          byte PMTLD2      :1;                        // PIT Micro Timer Load Bit 2  
          byte PMTLD3      :1;                        // PIT Micro Timer Load Bit 3  
          byte PMTLD4      :1;                        // PIT Micro Timer Load Bit 4  
          byte PMTLD5      :1;                        // PIT Micro Timer Load Bit 5  
          byte PMTLD6      :1;                        // PIT Micro Timer Load Bit 6  
          byte PMTLD7      :1;                        // PIT Micro Timer Load Bit 7  
        } Bits;
      } PITMTLD0STR;
      extern volatile PITMTLD0STR _PITMTLD0 @(REG_BASE + 0x00000346UL);
      #define PITMTLD0                        _PITMTLD0.Byte
      #define PITMTLD0_PMTLD0                 _PITMTLD0.Bits.PMTLD0
      #define PITMTLD0_PMTLD1                 _PITMTLD0.Bits.PMTLD1
      #define PITMTLD0_PMTLD2                 _PITMTLD0.Bits.PMTLD2
      #define PITMTLD0_PMTLD3                 _PITMTLD0.Bits.PMTLD3
      #define PITMTLD0_PMTLD4                 _PITMTLD0.Bits.PMTLD4
      #define PITMTLD0_PMTLD5                 _PITMTLD0.Bits.PMTLD5
      #define PITMTLD0_PMTLD6                 _PITMTLD0.Bits.PMTLD6
      #define PITMTLD0_PMTLD7                 _PITMTLD0.Bits.PMTLD7
   */
   
   PITLD0 = 799; 
         
   //为0通道16位计数器赋值   
   // PIT Load Register 0 to 3(PITLD0-3) 
   // 该寄存器用于设置PIT模块中的16位计数器初值,和8位计数器配合而成24位计数器。设定值范围0-655352
   // PITLD0的定义如下:
   /*
   // PITLD0 - PIT Load Register 0; 0x00000348  
        typedef union {
          word Word;
        } PITLD0STR;
        extern volatile PITLD0STR _PITLD0 @(REG_BASE + 0x00000348UL);
        #define PITLD0                   _PITLD0.Word
   */

      
    // 因位Fbus(总线时钟)= 40MHZ 
    // 故0通道的定时周期可以如下计算:
    // (249+1)*(799+1)/40M = 0.005s = 5ms.
    
   
  
     
                     

   PITMUX_PMUX0=0;   
   
   // 设置第0通道使用微计数器0
   // 
   /* // PITMUX - PIT Multiplex Register; 0x00000343  
      typedef union {
        byte Byte;
        struct {
          byte PMUX0       :1;                    // PIT Multiplex Bits for Timer Channel 0  
          byte PMUX1       :1;                    // PIT Multiplex Bits for Timer Channel 1  
          byte PMUX2       :1;                    // PIT Multiplex Bits for Timer Channel 2  
          byte PMUX3       :1;                    // PIT Multiplex Bits for Timer Channel 3  
          byte PMUX4       :1;                    // PIT Multiplex Bits for Timer Channel 4 
          byte PMUX5       :1;                    // PIT Multiplex Bits for Timer Channel 5  
          byte PMUX6       :1;                    // PIT Multiplex Bits for Timer Channel 6  
          byte PMUX7       :1;                    // PIT Multiplex Bits for Timer Channel 7  
        } Bits;
      } PITMUXSTR;
      extern volatile PITMUXSTR _PITMUX @(REG_BASE + 0x00000343UL);
      #define PITMUX                          _PITMUX.Byte
      #define PITMUX_PMUX0                    _PITMUX.Bits.PMUX0
      #define PITMUX_PMUX1                    _PITMUX.Bits.PMUX1
      #define PITMUX_PMUX2                    _PITMUX.Bits.PMUX2
      #define PITMUX_PMUX3                    _PITMUX.Bits.PMUX3
      #define PITMUX_PMUX4                    _PITMUX.Bits.PMUX4
      #define PITMUX_PMUX5                    _PITMUX.Bits.PMUX5
      #define PITMUX_PMUX6                    _PITMUX.Bits.PMUX6
      #define PITMUX_PMUX7                    _PITMUX.Bits.PMUX7
    */
  
   //  PIT定时器复合寄存器 PITMUX 如下:
   
   // bit   7        6        5        4       3      2        1         0
   //    ______________________________________________________________________
   // R |        |       |         |       |      |       |         |          |
   //   |  PMUX7 | PMUX6 |  PMUX5  | PMUX4 | PMUX3| PMUX2 | PMUX1   |   PMUX0  |
   // W |        |       |         |       |      |       |         |          |
   //   |________|_______|_________|_______|______|_______|_________|__________|
   //复位:  0       0         0        0      0       0         0         0
   
   // PMUX[7:0]: PIT定时器复合寄存器控制位. 
   //     该寄存器控制16位定时器与8位微定时器时基0或者时基1连接复合
   //     0: 相应16位定时器与微定时器时基0连接
   //     1: 相应16位定时器与微定时器时基1连接
   
   
   
   PITCE_PCE0=1;
        
   // 设置第0通道计数器工作
   // 
   /* // PITCE - PIT Channel Enable Register; 0x00000342  
      typedef union {
        byte Byte;
        struct {
          byte PCE0        :1;               // PIT Enable Bits for Timer Channel 0  
          byte PCE1        :1;               // PIT Enable Bits for Timer Channel 1  
          byte PCE2        :1;               // PIT Enable Bits for Timer Channel 2  
          byte PCE3        :1;               // PIT Enable Bits for Timer Channel 3  
          byte PCE4        :1;               // PIT Enable Bits for Timer Channel 4  
          byte PCE5        :1;               // PIT Enable Bits for Timer Channel 5  
          byte PCE6        :1;               // PIT Enable Bits for Timer Channel 6  
          byte PCE7        :1;               // PIT Enable Bits for Timer Channel 7  
        } Bits;
      } PITCESTR;
      extern volatile PITCESTR _PITCE @(REG_BASE + 0x00000342UL);
      #define PITCE                           _PITCE.Byte
      #define PITCE_PCE0                      _PITCE.Bits.PCE0
      #define PITCE_PCE1                      _PITCE.Bits.PCE1
      #define PITCE_PCE2                      _PITCE.Bits.PCE2
      #define PITCE_PCE3                      _PITCE.Bits.PCE3
      #define PITCE_PCE4                      _PITCE.Bits.PCE4
      #define PITCE_PCE5                      _PITCE.Bits.PCE5
      #define PITCE_PCE6                      _PITCE.Bits.PCE6
      #define PITCE_PCE7                      _PITCE.Bits.PCE7
    */      
   //  PIT通道使能寄存器 PITCE 如下:
   
   // bit   7        6        5        4       3      2        1         0
   //    ____________________________________________________________________
   // R |        |       |         |       |      |       |         |        |
   //   |  PCE7  | PCE6  |  PCE5   |  PCE4 |  PCE3|  PCE2 |  PCE1   |  PCE0  |
   // W |        |       |         |       |      |       |         |        |
   //   |________|_______|_________|_______|______|_______|_________|________|
   //复位:  0       0         0        0      0       0         0         0
  
   // PCE[7:0]:  PIT使能控制位.
   //     该寄存器使能PIT四个通道, 如果PCE写0, PIT通道将被禁止, PITTF(PIT溢出标志寄存器)中 
   //     相应的标志位也将被清除; 如果PCE写1, PIT通道将被使能, 16位定时器计数器被载入初始值
   //     并开始计数.
   //    0: 相应通道使能
   //    1: 相应通道禁止
   
   


   
   
   PITCFLMT=0x80;
       
   // 使能PIT模块
   // 我们进入头文件查询  PITCFLMT 的定义:
   /* 
   // PITCFLMT - PIT Control and Force Load Micro Timer Register; 0x00000340  
        typedef union {
          byte Byte;
          struct {
            byte PFLMT0      :1;             // PIT Force Load Bits for Micro Timer 0  
            byte PFLMT1      :1;             // PIT Force Load Bits for Micro Timer 1  
            byte             :1; 
            byte             :1; 
            byte             :1; 
            byte PITFRZ      :1;            // PIT Counter Freeze while in Freeze Mode Bit  
            byte PITSWAI     :1;            // PIT Stop in Wait Mode Bit  
            byte PITE        :1;            // PIT Module Enable Bit  
          } Bits;
          struct {
            byte grpPFLMT :2;
            byte         :1;
            byte         :1;
            byte         :1;
            byte         :1;
            byte         :1;
            byte         :1;
          } MergedBits;
        } PITCFLMTSTR;
        extern volatile PITCFLMTSTR _PITCFLMT @(REG_BASE + 0x00000340UL);
        #define PITCFLMT                        _PITCFLMT.Byte
        #define PITCFLMT_PFLMT0                 _PITCFLMT.Bits.PFLMT0
        #define PITCFLMT_PFLMT1                 _PITCFLMT.Bits.PFLMT1
        #define PITCFLMT_PITFRZ                 _PITCFLMT.Bits.PITFRZ
        #define PITCFLMT_PITSWAI                _PITCFLMT.Bits.PITSWAI
        #define PITCFLMT_PITE                   _PITCFLMT.Bits.PITE
        #define PITCFLMT_PFLMT                  _PITCFLMT.MergedBits.grpPFLMT
   */
   
  // PIT控制寄存器及强制载入微定时器寄存器 PITCFLMT 如下所示:  
      
   // bit   7        6        5        4       3      2        1         0
   //    ____________________________________________________________________
   // R |        |       |         |   0   |  0   |  0    |    0    |    0   |
   //   | PITE   |PITSWAI| PITFRZ  |_______|______|_______|_________|________|
   // W |        |       |         |       |      |       | PFLMT1  | PFLMT0 |
   //   |________|_______|_________|_______|______|_______|_________|________|
   //复位:  0       0         0        0      0       0         0         0
  
   //  PITE: PIT模块使能位. 
   //     0: 禁止PIT模块
   //     1: 使能PIT模块
   
   
   
   PITINTE_PINTE0=1; //0通道定时器定时中断被使能
   
   // 我们进入头文件查询 PITINTE 的定义:
   /* // PITINTE - PIT Interrupt Enable Register; 0x00000344 
      typedef union {
        byte Byte;
        struct {
          byte PINTE0      :1;               // PIT Time-out Interrupt Enable Bits for Timer Channel 0 
          byte PINTE1      :1;               // PIT Time-out Interrupt Enable Bits for Timer Channel 1 
          byte PINTE2      :1;               // PIT Time-out Interrupt Enable Bits for Timer Channel 2 
          byte PINTE3      :1;               // PIT Time-out Interrupt Enable Bits for Timer Channel 3 
          byte PINTE4      :1;               // PIT Time-out Interrupt Enable Bits for Timer Channel 4 
          byte PINTE5      :1;               // PIT Time-out Interrupt Enable Bits for Timer Channel 5 
          byte PINTE6      :1;               // PIT Time-out Interrupt Enable Bits for Timer Channel 6 
          byte PINTE7      :1;               // PIT Time-out Interrupt Enable Bits for Timer Channel 7 
        } Bits;
      } PITINTESTR;
      extern volatile PITINTESTR _PITINTE @(REG_BASE + 0x00000344UL);
      #define PITINTE                         _PITINTE.Byte
      #define PITINTE_PINTE0                  _PITINTE.Bits.PINTE0
      #define PITINTE_PINTE1                  _PITINTE.Bits.PINTE1
      #define PITINTE_PINTE2                  _PITINTE.Bits.PINTE2
      #define PITINTE_PINTE3                  _PITINTE.Bits.PINTE3
      #define PITINTE_PINTE4                  _PITINTE.Bits.PINTE4
      #define PITINTE_PINTE5                  _PITINTE.Bits.PINTE5
      #define PITINTE_PINTE6                  _PITINTE.Bits.PINTE6
      #define PITINTE_PINTE7                  _PITINTE.Bits.PINTE7
  */
   
   //  PIT 中断使能寄存器 PITINTE 如下所示:
     
   // bit   7        6        5        4       3      2        1         0
   //    ____________________________________________________________________
   // R |        |       |         |       |      |       |         |        |
   //   | PINTE7 | PINTE6| PINTE5  |PINTE4 |PINTE3| PINTE2|  PINTE1 | PINTE0 |
   // W |        |       |         |       |      |       |         |        |
   //   |________|_______|_________|_______|______|_______|_________|________|
   //复位:  0       0         0        0      0       0         0         0
   
   // PINTE[7:0] : PIT定时器溢出中断使能控制位.
   //    0: PIT相应通道溢出中断禁止
   //    1: PIT相应通道溢出中断使能 
                   
 }
 
 






/*************************************************************/
/*                      初始化端口                           */
/*************************************************************/
void INIT_port(void) 
{
  CONT1_dir = 1;
  CONT2_dir = 1;
  CONT3_dir = 1;
  CONT4_dir = 1;
  CONT1 = 0;
  CONT2 = 0;
  CONT3 = 0;
  CONT4 = 0;
  DATA_dir = 0xff;
  DATA = 0x00;
}



/*************************************************************/
/*                        延时函数                           */
/*************************************************************/
void delay(void) 
{
 unsigned int i,j;
 for(j=0;j<200;j++)
 for(i=0;i<60000;i++);
}





 //----------------------PIT模块-----------------------------------------------
 
/*************************************************************/
/*                  周期定时器0中断函数                      */
/*************************************************************/ 

#pragma CODE_SEG __NEAR_SEG NON_BANKED

// NON_BANKED一般位于0xc000-0xffff区域(非分页区), 而这个区域是16位单片机可以直接寻址的区域,
// 由于飞思卡尔16位单片机的中断向量是16位,所以中断函数只有被置于非分页区内才能被寻址到,
// 而__NEAR_SEG告诉编译器函数放在固定页中,只有固定页中的函数才能访问其他页的数据,
// 同时CODE_SEG定义了一个代码段.
// 如果不写这一句, 默认的是将函数存放在分页的flash里面,此时函数为far函数,
// 访问far函数是相当耗费时间的一件事, 中断函数毫无实时性可言.
// 一般只有中断函数时才用__NEAR_SEG, 对于一般函数来说__NEAR_SEG毫无作用



// 接下来是PIT模块的溢出中断响应函数, 
// 首先我们在"MC9S12XEP100.h" 找出PIT中通道0所对应的溢出中断源的地址, 如下:
// #define Vpit0           0xFF7AU
// 将 该地址 和 中断函数名 一起写入 "project.prm"中.
interrupt void PIT_INTER0(void)  

{   
    EnableInterrupts; 
    
    if(1 == PITTF_PTF0)     // PIT模块的0通道发生溢出中断.
    
    {
      
   
      PITTF_PTF0=1;     
      // 先写1清除
     
  switch(single)
  {
    case 1:
      CONT1 = 1;
      CONT2 = 0;
      CONT3 = 0;
      CONT4 = 0;
      DATA=shuma[data1];
      break;

    case 2:
      CONT1 = 0;
      CONT2 = 1;
      CONT3 = 0;
      CONT4 = 0;
      DATA=shuma[data2];
      break;

    case 3:
      CONT1 = 0;
      CONT2 = 0;
      CONT3 = 1;
      CONT4 = 0;
      DATA=shuma[data3];
      break;

    case 4:
      CONT1 = 0;
      CONT2 = 0;
      CONT3 = 0;
      CONT4 = 1;
      DATA=shuma[data4];
      break;
    
    default:
      break;
  }
  
  single +=1;
  if(single == 5) single = 1;

 }
}
#pragma CODE_SEG DEFAULT







/*************************************************************/
/*                           主函数                          */
/*************************************************************/
void main(void)

 {
 
	DisableInterrupts;
	
  INIT_PLL();
  
  Init_PIT();
  
  INIT_port();
  
  INIT_AD();
  
  LEDCPU_dir=1;
  
	EnableInterrupts;
	
	Start_ATD();
	
	ECT_TFLG1_C0F = 1;
  ECT_TC0 = ECT_TCNT + 1250;         //设置输出比较时间为5ms
	
	for(;;)
	
	{
	
	if (ATD0STAT0_SCF)        
	
	    // 一轮序列转换结束,SCF置1
	    //  ATD0STAT0_SCF ------- 转换序列完成标志位
      //      在单次转换模式时, 当转换完成后置位(SCAN=0) 
      //      在连续转换模式时, 当第一次转换完成后置位(SCAN=1)
      
      /*
      // ATD0STAT0 - ATD 0 Status Register 0; 0x000002C6 
          typedef union {
            byte Byte;
            struct {
              byte CC0         :1;                 // Conversion Counter 0 
              byte CC1         :1;                 // Conversion Counter 1 
              byte CC2         :1;                 // Conversion Counter 2 
              byte CC3         :1;                 // Conversion Counter 3 
              byte FIFOR       :1;                 // FIFO Over Run Flag 
              byte ETORF       :1;                 // External Trigger Overrun Flag 
              byte             :1; 
              byte SCF         :1;                 // Sequence Complete Flag 
            } Bits;
            struct {
              byte grpCC   :4;
              byte         :1;
              byte         :1;
              byte         :1;
              byte         :1;
            } MergedBits;
          } ATD0STAT0STR;
          extern volatile ATD0STAT0STR _ATD0STAT0 @(REG_BASE + 0x000002C6UL);
          #define ATD0STAT0                       _ATD0STAT0.Byte
          #define ATD0STAT0_CC0                   _ATD0STAT0.Bits.CC0
          #define ATD0STAT0_CC1                   _ATD0STAT0.Bits.CC1
          #define ATD0STAT0_CC2                   _ATD0STAT0.Bits.CC2
          #define ATD0STAT0_CC3                   _ATD0STAT0.Bits.CC3
          #define ATD0STAT0_FIFOR                 _ATD0STAT0.Bits.FIFOR
          #define ATD0STAT0_ETORF                 _ATD0STAT0.Bits.ETORF
          #define ATD0STAT0_SCF                   _ATD0STAT0.Bits.SCF
          #define ATD0STAT0_CC                    _ATD0STAT0.MergedBits.grpCC
      */
	
	{
	  
        ATD0STAT0_SCF =1;        // 写1清除   
        
       // 读转换结果寄存器
        AD_in0 = ATD0DR1L;
        AD_in1 = ATD0DR0L;
        
        data1 = AD_in0/1000;
        data2 = AD_in0%1000/100;
        data3 = AD_in0%1000%100/10;
        data4 = AD_in0%1000%100%10;
        delay();  
        
        if(AD_in0 > AD_in1)
      
        LEDCPU = 0;
        
      else
      
        LEDCPU = 1;  
           
      }
	}	 
	 
}

导入到开发板,观察到现象:


拨动电位计:


2015-11-19 15:36:19 hexiechina2010 阅读数 1628
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4000 人正在学习 去看看 朱有鹏

今天做AD多通道采集,用SPI的方式,从功能板到主板发送AD多通道采集到的数据,用DMA的方式存入外存中。

测试过程中遇到的问题

1.有传通道的情况出现,就是A通道的数据显示到B通道的位置上去了,

调试方法,

1.先看功能板采集的波形的通道是否正常。

2.看少数据量时是否出错。

最后发现的问题是DMA设置的缓冲区的长度不是(AD采集的通道数*AD采集的位宽)的整数倍。


2013-08-07 11:34:40 raoqin 阅读数 2949
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4000 人正在学习 去看看 朱有鹏

        这里是这几天做的实验,在安卓上的软件程序主要参考《疯狂的安卓讲义》,电路中的一些东西参考的是HiJack项目中的电路。在这里,我真的突然感慨学好模电真的很重要。在没有参考HIJACK之前,我对这些音频信号手足无措。在这个小项目学习完后,我决定再重新学习模电,感觉这一次重温应该能让我这模电知识再上一个台阶。

下面我从几个方面记录一下自己的学习过程,给自己留个记录以后翻阅,也可以给大家一个参考;

1).耳机线的接口;

2).话筒和耳机的声音原理;

3).安卓中的程序编写


1.耳机接口问题

        一般MP3中的耳机就真的是耳机,其中没有话筒,分为三段左声道、右声道、地。而我们的手机中原装的耳机是带有话筒的,这种耳机分为四段分别为左声道、右声道、地、MIC。就是这手机带的四段带话筒的耳机还不同,像国内的一些手机厂商和国外的厂商,这种耳机的地和MIC可能是对换了的。有条件的可以折几个测测就知道。


2.其实话筒接收的是振动信号,以些振动信号产生变化的电流,通过耳机接口传到手机里面的处理电路,最后被采样。所以,这里用以下电路,参考HIJACK中的,单片机用PWM来输出。

用的是1KHZ占空比为50%的PWM波,最后在安卓中保存话筒采集到的数据,用的是16bit单通道格式保存为PCM,显示的波形图如下:振动幅值都是最大的-32768,32767.


在手机播放500HZ的音频时,我在耳机中测到的输入波形如下图:C1即为在左声道测得的波形,Z1、Z2为放大后的。

从手机通过耳机到单片机的电路如下:


3.安卓中的程序主要是涉及两个模块,一个是音频的录放,另一个就是文件的存储;

程序如下:APK编写的时候是支持android2.3.1以上的,大家可以在资源里下载http://download.csdn.net/detail/raoqin/5884203


界面文件main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_height="fill_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent">

    <Button android:layout_height="wrap_content" android:text="开始边录边放" 
            android:layout_width="fill_parent" android:id="@+id/btnRecord"></Button>
    <Button android:id="@+id/btnStop" android:layout_width="fill_parent" 
            android:text="停止" android:layout_height="wrap_content"></Button>
    <Button android:layout_width="fill_parent" android:layout_height="wrap_content" 
            android:id="@+id/btnExit" android:text="退出"></Button>
    <TextView android:id="@+id/TextView01" android:layout_height="wrap_content" 
            android:layout_width="fill_parent" android:text="程序音量调节"></TextView>
    <SeekBar android:layout_width="fill_parent" android:id="@+id/skbVolume" 
            android:layout_height="wrap_content"></SeekBar>
    <TableRow android:layout_width="match_parent" android:layout_height="wrap_content" 
            android:id="@+id/tableRow1">
        <Button android:id="@+id/read" android:layout_height="wrap_content" 
            android:layout_width="wrap_content" android:text="读"></Button>
        <Button android:id="@+id/write" android:layout_height="wrap_content" 
            android:layout_width="wrap_content" android:text="写"></Button>
    </TableRow>
    <EditText android:hint="EditText" android:id="@+id/edit1" 
              android:layout_width="match_parent" android:layout_height="wrap_content"></EditText>
    <EditText android:layout_width="match_parent" android:hint="EditText" 
              android:id="@+id/edit2" android:layout_height="wrap_content"></EditText>

</LinearLayout> 

主程序如下:

package packname.test;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.RandomAccessFile;

import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.Toast;

public class acti extends Activity 
{
	/** Called when the activity is first created. */
	//----
	final String FILE_NAME = "/myraoqin.bin";
	File sdCardDir = null;
	File targetFile = null;
	RandomAccessFile raf = null;
	//----
	Button btnRecord, btnStop, btnExit;
	SeekBar skbVolume;//调节音量
	boolean isRecording = false;//是否录放的标记
	static final int frequency = 44100;
	static final int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
	static final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;//AudioFormat.ENCODING_PCM_16BIT;
	int recBufSize,playBufSize;
	AudioRecord audioRecord;
	AudioTrack audioTrack;

	@Override
	public void onCreate(Bundle savedInstanceState) 
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		setTitle("Lhyraoqin");
		//----------------------------SD卡文件 
		//获取SD卡的目录
		try
		{
		sdCardDir = Environment.getExternalStorageDirectory();
		targetFile = new File(sdCardDir.getCanonicalPath() + FILE_NAME );
		//以指定文件创建 randomaccessfile对象
		raf = new RandomAccessFile( targetFile, "rw" );
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		//获取两个按钮
		Button read = (Button) findViewById(R.id.read);
		Button write = (Button) findViewById(R.id.write);
		//获取两个文本框
		final EditText edit1 = (EditText) findViewById(R.id.edit1);
		final EditText edit2 = (EditText) findViewById(R.id.edit2);
		//为write按钮绑定事件监听器
		write.setOnClickListener(new View.OnClickListener()
		{
			@Override
			public void onClick(View source)
			{
				//将edit1中的内容写入文件中
				Mywrite(edit1.getText().toString());
				edit1.setText("");
			}
		});
		read.setOnClickListener(new View.OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				//读取指定文件中的内容并显示出来
				edit2.setText(Myread());
			}
		});
		//-------------------------SD文件
		//-----
		recBufSize = AudioRecord.getMinBufferSize(frequency,
				channelConfiguration, audioEncoding);

		playBufSize=AudioTrack.getMinBufferSize(frequency,
				channelConfiguration, audioEncoding);
		// -----------------------------------------
		audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, frequency,
				channelConfiguration, audioEncoding, recBufSize);

		audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, frequency,
				channelConfiguration, audioEncoding,
				playBufSize, AudioTrack.MODE_STREAM);
		//------------------------------------------
		btnRecord = (Button) this.findViewById(R.id.btnRecord);
		btnRecord.setOnClickListener(new ClickEvent());
		btnStop = (Button) this.findViewById(R.id.btnStop);
		btnStop.setOnClickListener(new ClickEvent());
		btnExit = (Button) this.findViewById(R.id.btnExit);
		btnExit.setOnClickListener(new ClickEvent());
		skbVolume=(SeekBar)this.findViewById(R.id.skbVolume);
		skbVolume.setMax(100);//音量调节的极限
		skbVolume.setProgress(70);//设置seekbar的位置值
		audioTrack.setStereoVolume(0.7f, 0.7f);//设置当前音量大小
		skbVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() 
		{
			
			@Override
			public void onStopTrackingTouch(SeekBar seekBar) 
			{
				float vol=(float)(seekBar.getProgress())/(float)(seekBar.getMax());
				audioTrack.setStereoVolume(vol, vol);//设置音量
			}
			
			@Override
			public void onStartTrackingTouch(SeekBar seekBar) 
			{
				// TODO Auto-generated method stub
			}
			
			@Override
			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) 
			{
				// TODO Auto-generated method stub
			}
		});
	}
	//------------
	//读写文件用的
	//
	//
	//----------------
	private String Myread()
	{
		try
		{
			//如果手机插入了SD卡,而且应用程序具有访问SD的权限
			if(Environment.getExternalStorageState()
					.equals(Environment.MEDIA_MOUNTED) )
			{
				//获取SD卡的目录
				File sdCardDir = Environment.getExternalStorageDirectory();
				//获取指定文件对应的输入流
				FileInputStream fis = new FileInputStream(sdCardDir.getCanonicalPath() + FILE_NAME);
				//将指定输入流包装成Bufferreader
				BufferedReader br = new BufferedReader(new InputStreamReader(fis));
				StringBuilder sb = new StringBuilder("");
				String line = null;
				
				while((line = br.readLine()) != null)
				{
					sb.append(line);
				}
				return sb.toString();
			}
			/*
			//打开文件输入流
			FileInputStream fis = openFileInput("myFILE_NAME");
			byte[] buff = new byte[1024];
			int hasRead = 0;
			StringBuilder sb = new StringBuilder("");
			while( (hasRead = fis.read(buff)) > 0 )
			{
				sb.append(new String(buff, 0, hasRead));
			}
			return sb.toString();
			*/
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}
	//-------------------------
	//读写文件用的
	//
	//
	//---------------------------------
	private void Mywrite(String content)
	{
		try
		{
			//如果手机插入了SD卡,而且应用程序具有访问SD的权限
			if(Environment.getExternalStorageState()
					.equals(Environment.MEDIA_MOUNTED) )
			{
				/*
				//获取SD卡的目录
				File sdCardDir = Environment.getExternalStorageDirectory();
				File targetFile = new File(sdCardDir.getCanonicalPath() + FILE_NAME );
				//以指定文件创建 randomaccessfile对象
				RandomAccessFile raf = new RandomAccessFile( targetFile, "rw" );
				*/
				
				//输出文件内容
				raf.write(content.getBytes());
				byte[] mybytes = new byte[3];
				
				//raf.close();
			}
				/*
				//以追加模式打开文件输出流
				FileOutputStream fos = openFileOutput("myFILE_NAME", MODE_APPEND);
				//将fileoutputstream包装成printstream
				PrintStream ps = new PrintStream(fos);
				//输出文件内容
				ps.println(content);
				ps.close();
				*/
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	//-------------------------
		//读写文件用的
		//
		//
		//---------------------------------
		private void Mywrite(byte[] mybytes)
		{
			try
			{
				//如果手机插入了SD卡,而且应用程序具有访问SD的权限
				if(Environment.getExternalStorageState()
						.equals(Environment.MEDIA_MOUNTED) )
				{
					//输出文件内容
					raf.write(mybytes);				
				}
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
		}
	
	//-------------------------
	//
	//
	//
	//---------------------------------
	@Override
	protected void onDestroy() 
	{
		try 
		{
			raf.close();
		} 
		catch (IOException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		super.onDestroy();
		android.os.Process.killProcess(android.os.Process.myPid());
	}

	class ClickEvent implements View.OnClickListener 
	{

		@Override
		public void onClick(View v) 
		{
			if (v == btnRecord) 
			{
				isRecording = true;
				new RecordPlayThread().start();// 开一条线程边录边放
			} 
			else if (v == btnStop) 
			{
				isRecording = false;
			} 
			else if (v == btnExit) 
			{
				isRecording = false;
				acti.this.finish();
			}
		}
	}

	class RecordPlayThread extends Thread 
	{
		public void run() 
		{
			try 
			{
				byte[] buffer = new byte[recBufSize];
				audioRecord.startRecording();//开始录制
				audioTrack.play();//开始播放
				
				while (isRecording) 
				{
					//从MIC保存数据到缓冲区
					int bufferReadResult = audioRecord.read(buffer, 0,
							recBufSize);

					byte[] tmpBuf = new byte[bufferReadResult];
					
					System.arraycopy(buffer, 0, tmpBuf, 0, bufferReadResult);
					//for(int i=0; i<bufferReadResult; i++)
					//{
						/*
						if( i%32 ==0 ) tmpBuf[i] = 1;
						if( i%32 ==1 ) tmpBuf[i] = 11;
						if( i%32 ==2 ) tmpBuf[i] = 1;
						if( i%32 ==3 ) tmpBuf[i] = 11;
						if( i%32 ==4 ) tmpBuf[i] = 1;
						if( i%32 ==5 ) tmpBuf[i] = 11;
						if( i%32 ==6 ) tmpBuf[i] = 1;
						if( i%32 ==7 ) tmpBuf[i] = 11;
						if( i%32 ==8 ) tmpBuf[i] = 1;
						if( i%32 ==9 ) tmpBuf[i] = 11;
						if( i%32 ==10 ) tmpBuf[i] = 1;
						if( i%32 ==11 ) tmpBuf[i] = 11;
						if( i%32 ==12 ) tmpBuf[i] = 1;
						if( i%32 ==13 ) tmpBuf[i] = 11;
						if( i%32 ==14 ) tmpBuf[i] = 1;
						if( i%32 ==15 ) tmpBuf[i] = 11;
						
						if( i%32 ==16 ) tmpBuf[i] = 1;
						if( i%32 ==17 ) tmpBuf[i] = -11;
						if( i%32 ==18 ) tmpBuf[i] = 1;
						if( i%32 ==19 ) tmpBuf[i] = -11;
						if( i%32 ==20 ) tmpBuf[i] = 1;
						if( i%32 ==21 ) tmpBuf[i] = -11;
						if( i%32 ==22 ) tmpBuf[i] = 1;
						if( i%32 ==23 ) tmpBuf[i] = -11;
						if( i%32 ==24 ) tmpBuf[i] = 1;
						if( i%32 ==25 ) tmpBuf[i] = -11;
						if( i%32 ==26 ) tmpBuf[i] = 1;
						if( i%32 ==27 ) tmpBuf[i] = -11;
						if( i%32 ==28 ) tmpBuf[i] = 1;
						if( i%32 ==29 ) tmpBuf[i] = -11;
						if( i%32 ==30 ) tmpBuf[i] = 1;
						if( i%32 ==31 ) tmpBuf[i] = -11;
						*/
						/*
						if( i%32 ==0 ) tmpBuf[i] = 1;
						if( i%32 ==1 ) tmpBuf[i] = 11;
						if( i%32 ==2 ) tmpBuf[i] = 1;
						if( i%32 ==3 ) tmpBuf[i] = 11;
						if( i%32 ==4 ) tmpBuf[i] = 1;
						if( i%32 ==5 ) tmpBuf[i] = 11;
						if( i%32 ==6 ) tmpBuf[i] = 1;
						if( i%32 ==7 ) tmpBuf[i] = 11;
						if( i%32 ==8 ) tmpBuf[i] = 1;
						if( i%32 ==9 ) tmpBuf[i] = 11;
						if( i%32 ==10 ) tmpBuf[i] = 1;
						if( i%32 ==11 ) tmpBuf[i] = 11;
						if( i%32 ==12 ) tmpBuf[i] = 1;
						if( i%32 ==13 ) tmpBuf[i] = 11;
						if( i%32 ==14 ) tmpBuf[i] = 1;
						if( i%32 ==15 ) tmpBuf[i] = 11;
						
						if( i%32 ==16 ) tmpBuf[i] = -1;
						if( i%32 ==17 ) tmpBuf[i] = 11;
						if( i%32 ==18 ) tmpBuf[i] = -1;
						if( i%32 ==19 ) tmpBuf[i] = 11;
						if( i%32 ==20 ) tmpBuf[i] = -1;
						if( i%32 ==21 ) tmpBuf[i] = 11;
						if( i%32 ==22 ) tmpBuf[i] = -1;
						if( i%32 ==23 ) tmpBuf[i] = 11;
						if( i%32 ==24 ) tmpBuf[i] = -1;
						if( i%32 ==25 ) tmpBuf[i] = 11;
						if( i%32 ==26 ) tmpBuf[i] = -1;
						if( i%32 ==27 ) tmpBuf[i] = 11;
						if( i%32 ==28 ) tmpBuf[i] = -1;
						if( i%32 ==29 ) tmpBuf[i] = 11;
						if( i%32 ==30 ) tmpBuf[i] = -1;
						if( i%32 ==31 ) tmpBuf[i] = 11;
						*/
					//}
					Mywrite(tmpBuf);
					//写入数据即播放
					int xiedeshu = audioTrack.write(tmpBuf, 0, tmpBuf.length);
					
				}
				audioTrack.stop();
				audioRecord.stop();
			} 
			catch (Throwable t) 
			{
				Toast.makeText(acti.this, t.getMessage(), 1000);
			}
		}
	};
}

最后记得在AndroidManifest.xml文件中加入权限

<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission> 

程序将把录到的PCM文件保存到SD上的myraoqin.bin文件中,这个文件就是16bit单通道文件,可以用GoldWave软件打开进行播放测试。


AFE4400的使用

阅读数 2785

电压电流采样

阅读数 6231

水温系统设计

阅读数 3660

没有更多推荐了,返回首页