这是我大三时的课程设计,设计要求如下:

1.时栅传感器模拟器:通过输入两路时间和空间的信号。

(1) 设计一路正弦载波信号模拟信号输出 sina * cos(wt)

(2) 设计一路余弦信号模拟信号输出     cosa *sin(wt)
    (3) 设计两路信号的合成模拟信号输出   sin(wt+a)
2. 设计数据采集模块。(要求整周期采样)

3.  ARM硬件接口电路设计:显示路和键盘电路

4. 软件设计:数字相关算法求解角度、显示、按键、A/D.
5.  proteus仿真和实做。希望对大家有用!

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
image.png
LPC2138单片机源程序如下:
#include  "config.h"
  • //#include  "LPC21xx.h"
  • #include "math.h"
  • //#define Fpclk 12000000
  • //typedef unsigned char  uint8;                   /* defined for unsigned 8-bits integer variable         无符号8位整型变量  */
  • //typedef signed   char  int8;                    /* defined for signed 8-bits integer variable                有符号8位整型变量  */
  • //typedef unsigned short uint16;                  /* defined for unsigned 16-bits integer variable         无符号16位整型变量 */
  • //typedef signed   short int16;                   /* defined for signed 16-bits integer variable                 有符号16位整型变量 */
  • //typedef unsigned int   uint32;                  /* defined for unsigned 32-bits integer variable         无符号32位整型变量 */
  • //typedef signed   int   int32;                   /* defined for signed 32-bits integer variable                 有符号32位整型变量 */
  • //typedef float          fp32;                    /* single precision floating point variable (32bits) 单精度浮点数(32位长度) */
  • //typedef double         fp64;                    /* double precision floating point variable (64bits) 双精度浮点数(64位长度) */
  • #define IO_RS   0x1000000
  • #define IO_RW   0x2000000
  • #define IO_EN   0x4000000
  • #define LED 0X01
  • #define KEY1 (IO0PIN&(1<<20))
  • #define KEY2 (IO0PIN&(1<<21))   
  •       
  • int32  k=0,ADC_Data,tt1,tt2;
  • uint32 A=1,FG1=1,FG2=2;
  • uint32 a,i,h,j,p,q,m,n,u,v;
  • double c,s,data_1=0,data_2=0,data_3=0,data_4=0;
  • double x,y,PI=3.141592653589793238462643383279502;
  • int32 Buffer[256];
  • double SINCE[19]={
  • 0.0000,0.0872,0.1736,0.2588,0.3420,0.4226,
  • 0.5000,0.5736,0.6428,0.7071,0.7660,0.8192,
  • 0.8660,0.9063,0.9397,0.9659,0.9848,0.9962,
  • 1.0000,
  • };
  • double COSCE[19]={
  • 1.0000,0.9962,0.9848,0.9659,0.9397,0.9063,
  • 0.8660,0.8192,0.7660,0.7071,0.6428,0.5736,
  • 0.5000,0.4226,0.3420,0.2588,0.1736,0.0872,
  • 0.0000,
  • };
  •         
  • const int16 sindata[]={
  • 0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,
  • 0x98,0x9b,0x9e,0xa1,0xa4,0xa7,0xaa,0xad,
  • …………
  • …………限于本文篇幅 余下代码请从51黑下载附件…………
  • 0xfc,0xfd,0xfd,0xfe,0xfe,0xfe,0xfe,0xfe,
  • };
  • #define RS_1    IO1SET=(IO_RS&0xFFFFFFFF)
  • #define RS_0    IO1CLR=(IO_RS&0xFFFFFFFF)
  • #define RW_1    IO1SET=(IO_RW&0xFFFFFFFF)
  • #define RW_0    IO1CLR=(IO_RW&0xFFFFFFFF)
  • #define EN_1    IO1SET=(IO_EN&0xFFFFFFFF)
  • #define EN_0    IO1CLR=(IO_EN&0xFFFFFFFF)
  • void delayms(unsigned int t)
  • {
  •         unsigned char u,v;
  •         for(u=0;u<100;u++)
  •          for(v=0;v<81;v++);
  • }
  • void LCD_write_com(unsigned char com)              //LCD写入命令函数
  • {
  •         RS_0;
  •         RW_0;
  •         EN_1;
  •         IO1SET=com<<16;
  •         delayms(5);
  •         EN_0;
  •         IO1CLR=0xFF0000;
  • }
  • void LCD_write_data(unsigned char data)           //写入数据函数
  • {
  •         RS_1;
  •   RW_0;
  •   EN_1;
  •   IO1SET=data<<16;
  •         delayms(5);        
  •   EN_0;
  •         IO1CLR=0xFF0000;
  • }
  • void LCD_clear()                                  //LCD清屏函数
  • {
  •         LCD_write_com(0x01);
  •         delayms(5);
  • }
  • void LCD_write_char(unsigned char x,unsigned char y,unsigned char s)    //写入字符函数
  • {     
  • if (y == 0)
  •          {     
  •          LCD_write_com(0x80+x);     
  •          }   
  • else
  •          {     
  •          LCD_write_com(0xC0+x);     
  •          }        
  • LCD_write_data(s);  
  • }
  • void LCD_write_string(unsigned char x,unsigned char y,unsigned char *s)   //写入字符串函数
  • {     
  • if (y == 0)
  •          {     
  •          LCD_write_com(0x80 + x);     //表示第一行
  •          }
  • else
  •          {      
  •          LCD_write_com(0xC0 + x);      //表示第二行
  •          }        
  • while (*s)
  •          {     
  •     LCD_write_data( *s);     
  •     s++;     
  •          }
  • }
  • void LCD_init()      //LCD初始化
  • {
  •         LCD_write_com(0x38);          //显示模式设置
  •         delayms(5);
  •         LCD_write_com(0x38);
  •         delayms(5);
  •         LCD_write_com(0x38);
  •         delayms(5);
  •         LCD_write_com(0x38);        
  •         LCD_write_com(0x08);               //显示关闭
  •         LCD_write_com(0x01);         //清屏
  •         LCD_write_com(0x06);         //显示光标移动设置
  •         delayms(5);
  •         LCD_write_com(0x0C);         //显示开及光标设置
  •   
  • }
  • /*
  • void  UART0Init(uint32 bps)
  • {  
  •     uint16 Fdiv;
  •     PINSEL0 = (PINSEL0 & (~0x0F)) | 0x05;        
  •     U0LCR = 0x83;                                                        
  •     Fdiv = (Fpclk / 16) / bps;                        
  •     U0DLM = Fdiv / 256;                                                        
  •     U0DLL = Fdiv % 256;                                                
  •     U0LCR = 0x03;
  • }
  • */
  •    void __irq IRQ_Timer0 (void)
  • {   
  • //            for(i=0;i<256;i++)
  • //            {         
  • //                                y=COSCE[a];
  • //                                x=SINCE[a];
  • //                                s=(y*sindata[i]);
  • //                                c=(x*cosdata[i]);
  • //                                
  • //                                sindata[i]=sin(2.0*acos(-1.0)/256*i);
  • //                                cosdata[i]=cos(2.0*acos(-1.0)/256*i);
  • //                                
  • //                                h=(s*0x1ff+0x1ff);
  • //                                h=s+c;
  • //                                DACR=((sindata[i]<<6))|(1<<16);
  • //                                for(j=0;j<0x20;j++);
  •         
  •                         if((IO0PIN&KEY1)==0)
  •        {
  •                            if(FG1!=(A-5))
  •                            {
  •                                FG1=A;A+=5;i=0;
  •                                            if(A>360) A=0;
  •                            }
  •                          }
  •                         
  •       if((IO0PIN&KEY1)!=0){ FG1=1; }
  •                           a=A*180/PI;
  •                   if((IO0PIN&KEY2)==0)
  •        {
  •                              if(FG2!=(A+5))
  •                          {FG2=A;A-=5;i=0;
  •                          if(A>360)A=0;}
  •                          }
  •                         if((IO0PIN&KEY2)!=0){ FG2=1; }
  •                         if(A<=90)   a=A/5;
  •                         if(A>90&A<=180)  a=36-A/5;
  •                         if(A>180&A<270)  a=A/5-36;
  •                         if(A>=270&A<360) a=72-A/5;
  •                         
  •                         y=COSCE[a];
  •                   x=SINCE[a];
  •                         s=(y*sindata[i]);
  •                         c=(x*cosdata[i]);
  •                         
  • //                        sindata[i]=sin(2.0*acos(-1.0)/256*i);
  • //                        cosdata[i]=cos(2.0*acos(-1.0)/256*i);
  •                         
  • //                        h=(s*0x1ff+0x1ff);
  •                         h=s+c;
  •                         DACR=((h<<6))|(1<<16);
  •                         for(j=0;j<0x20;j++);
  •       
  •                
  •                         AD0CR = (AD0CR&0x00FFFF00)|0x01|(1 << 24);        // 设置AD0.0,并进行第一次转换
  •                         while( (AD0DR&0x80000000)==0 );                    // 等待转换结束
  •                         ADC_Data = AD0DR;                                                        // 读取ADC结果
  •                         ADC_Data = (ADC_Data>>6) & 0x3FF;           // 提取AD转换值
  •                         
  •                         Buffer[i]=ADC_Data;
  •            
  •            LCD_write_char(9,0,A/100%10+0X30);
  •            LCD_write_char(10,0,A/10%10+0X30);
  •            LCD_write_char(11,0,A%10+0X30);
  •                 for(u=0;u<256;u++)
  •                 {
  •                         data_1 = data_1 +(Buffer[u]-0x7f)*(cosdata[u]-0x7f)/256;//-5170)*PI/128;
  •                         data_2 = data_2 +(Buffer[u]-0x7f)*(sindata[u]-0x7f)/256;//-5170)*PI/128;        
  •                 }
  •                         data_4 = atan(data_1 /data_2)*180/acos(-1.0);
  •                         tt1=data_4*10;//1;
  •                         
  •                         if(A>90&A<180)   tt1=1800-tt1;
  •                         if(A>180&A<270)  tt1=1800+tt1;  
  •                         if(A>270&A<360)  tt1=3600-tt1;  
  •                
  •                         LCD_write_char(9,1,tt1/1000%10+0X30);        
  •                         LCD_write_char(10,1,tt1/100%10+0X30);
  •                         LCD_write_char(11,1,tt1/10%10+0X30);
  •                         LCD_write_char(12,1,'.');
  •                         LCD_write_char(13,1,tt1%10+0X30);
  •            
  • //        LCD_write_char(6,1,tt2/1000%10+0X30);        
  • //        LCD_write_char(7,1,tt2/100%10+0X30);
  • //    LCD_write_char(8,1,tt2/10%10+0X30);
  • //    LCD_write_char(9,1,'.');
  • //        LCD_write_char(10,1,tt2%10+0X30);
  •     i++;
  •     if(i>=256) i=0;
  •           T0IR = 0x02;                                /* 清除中断标志                                                                        */
  •           VICVectAddr = 0x00;                        /* 通知VIC中断处理结束                                                        */
  • //}
  • }
  • void  Time0Init(void)
  • {  
  •            T0TC   = 0;                              // 定时器T0初始化
  •            T0PR = 10;              // 设置定时器0分频为100分频,得120000Hz
  •     T0MCR = 0x03<<3;                // 匹配通道MR1匹配中断并复位TC
  •           T0MR0 = Fpclk/12000;          // MR0比较值(0.5秒定时值)
  •           T0MR1 = Fpclk/1200;          // MR1比较值(0.5秒定时值)
  •     T0EMR = 0x30;                    // 设置定时器0的MR0匹配输出,输出方式为翻转
  •           T0TCR = 0x03;           // 启动并复位T0TC
  •           T0TCR = 0x01;      
  •     T0IR = 0x02;
  •    /* 设置定时器0中断IRQ */
  •    VICIntSelect = 0x00;                                        // 所有中断通道设置为IRQ中断
  •    VICVectCntl0 = 0x20 | 0x04;                         // 分配定时器0中断到通道0(最高优先级)
  •    VICVectAddr0 = (uint32)IRQ_Timer0;         // 设置中断服务程序地址向量
  •    VICIntEnable = (1<<4);                    // 使能定时器0中断
  • //   IRQEnable();                                                 // 使能IRQ中断
  • }
  • int  main(void)
  • {            
  •     PINSEL0|=0x00000000;               
  •            PINSEL1 |= 0x01400000;
  •           PINSEL1 = (PINSEL1&(~(0x03<<18))) | (0x02<<18); // P0.25 连接Aout
  • //    UART0Init(9600);
  •     IO0DIR|=0X01;                                                
  •           IO1DIR|=0x07ff0000;
  •            LCD_init();                                                               
  •           Time0Init();
  •     AD0CR = (1 << 0)                    |        
  •            ((Fpclk / 1000000 - 1) << 8) |         
  •            (0 << 16)                    |        
  •            (0 << 17)                    |         
  •            (1 << 21)                    |                 
  •            (0 << 22)                    |                 
  •            (1 << 24)                    |                 
  •            (0 << 27);                                                        
  •     delayms(10);                                                               
  •     ADC_Data = AD0DR;
  •           LCD_write_string(0,0,"in:");
  •           LCD_write_string(0,1,"out:");               
  •         
  •     while(1)
  •     {
  • //                   y=COSCE[a];
  • //                                x=SINCE[a];
  • //                                s=(y*sindata[i]);
  • //                                c=(x*cosdata[i]);
  •                                 
  • //                                sindata[i]=sin(2.0*acos(-1.0)/256*i);
  • //                                cosdata[i]=cos(2.0*acos(-1.0)/256*i);
  •                                 
  • ……………………
  • …………限于本文篇幅 余下代码请从51黑下载附件…………
  • 复制代码