1.时栅传感器模拟器:通过输入两路时间和空间的信号。
(1) 设计一路正弦载波信号模拟信号输出 sina * cos(wt)
(2) 设计一路余弦信号模拟信号输出 cosa *sin(wt)
(3) 设计两路信号的合成模拟信号输出 sin(wt+a)
2. 设计数据采集模块。(要求整周期采样)
3. ARM硬件接口电路设计:显示路和键盘电路
4. 软件设计:数字相关算法求解角度、显示、按键、A/D.
5. proteus仿真和实做。希望对大家有用!
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
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黑下载附件…………
复制代码