1. 原理图如下,超声波测距,然后数码管显示距离
2. 代码如下
#include <hidef.h> /* for EnableInterrupts macro */ #include "derivative.h" /* include peripheral declarations */ #define uchar unsigned char #define uint unsigned int #define LED_PORT PTB #define LED_1 PTD_PTD5 #define LED_3 PTD_PTD4 #define LED_2 PTA_PTA5 //1 怎么检测输入引脚的电压 #define CSB_OUT PTD_PTD7 #define CSB_IN PTD_PTD6 #define DIS_VALUE_MIN 20 #define DIS_VALUE_MAX 500 //#define TEMP_REF 22 #define csb_speed 34 //1 xm0,xm1,xm2是定时器的测量值 uchar buffer[3]; //2 数码管的变量值 //uchar convert[10]={0x90,0xDE,0xA2,0x8A,0xCC,0x89,0x81,0xDA,0x80,0x88}; uchar convert[10]={0x08,0x6B,0x12,0x42,0x61,0x44,0x04,0x6A,0x00,0x60}; unsigned long int dis_value , timer_value; //float csb_speed,temper_value; //3 目前看来有两种下载方式,我使用codewarrior // 现在问题是,仿真器不能识别,难道是因为我用的USB转串口?? void csb_test(); void delay(int i); void led_display(); void offmsd(); void csb_send(); void csbsc(); void timer_init(); void csb_send(void) { unsigned int i = 10; //1 时钟是2.4576M,除以40Khz // 要不要找个示波器测试一下,看是否OK // //while(i--) { CSB_OUT = 1; delay(10); CSB_OUT = 0; //delay(60); } } //1 我在仿真测试这个的时候,发现,每次cycle + 20,这个是什么意思? // 其他普通语句,每次加4,目前晶振是4分频供给MCU,总线频率和CPU的频率一样吗? // 芯片内部有一个50KHZ的时钟,供给COP和SIM,这两个是什么? void delay(unsigned int i) { while(--i); } void led_display() { uint xm0,xm1,xm2; uchar i; //1 大于5米的时候,显示“CCC” if(dis_value>DIS_VALUE_MAX) { buffer[0]=0x3f; buffer[1]=0x3f; buffer[2]=0x3f; } //2 小于40厘米的时候吗,显示--- else if(dis_value<DIS_VALUE_MIN) { buffer[2]=0xf7; buffer[1]=0xf7; buffer[0]=0xf7; } else { xm0=dis_value/100; xm1=dis_value%100/10; xm2=dis_value%10; buffer[0]=convert[xm0]; buffer[1]=convert[xm1]; buffer[2]=convert[xm2]; } i= 1000; while(i--) { LED_PORT = buffer[0]; LED_1 = 0; delay(50); LED_1 = 1; LED_PORT = buffer[1]; LED_2=0; delay(50); LED_2=1; LED_PORT = buffer[2]; LED_3=0; delay(50); LED_3=1; } CSB_OUT=1; } //1 百位为零的时候不显示 void offmsd() { if (buffer[2]==0x08) buffer[2] = 0xff; } void csb_test() { unsigned int i; //2 难道是发送8KHZ的脉冲10次的意思? unsigned char test_num = 5; dis_value = 0; while(test_num--) { delay(3000); //csb_send(); //2 发射引脚拉高 CSB_OUT = 1; delay(25); CSB_OUT = 0; //3 开启定时器0 //4 延时一会 // 盲区值(延时躲过超声波发送头的余波) // 50对应时间 这个是 64分频的35,1分频是2226,2分频是1113,4分频是556,那么 // 分频就是提高了频率,那不对啊 ,怎么变小了。 64分频的是35,难道是计数器溢出了。 // 245对应时间 165 // 200对应时间135 // 测算下来是0.675倍左右 // 现在设置为1分频 while(CSB_IN == 0); T1SC_TRST = 1; T1SC_TSTOP = 0; //5 这个也算是延时吗,加标志位?我草 // CSB_IN不就是那个超声波的接收脚吗? // 这哥们的程序也太烂了,主要是这名字写的,哎~~ // 这里CSB_IN不对吧,看样子,这个芯片也是分输入输出的吧 // 第二个问题,就算引脚设置不对,disvalue也应该是有值的,不是0吧。先解决这个问题吧 // 看样子这个默认没执行? // 还好,原来这个输入和输出都是同一个,太好了。哈哈 while(CSB_IN == 1); //6 关闭定时器之后开始计 //7 难道定时器根本就没有开启来,用仿真测试一下吧 T1SC_TSTOP = 1; timer_value=T1CNTH; timer_value=timer_value*256+T1CNTL; //7 原来csb_speed是超声波的速度 // 查看寄存器 timer_value 是165,但是为什么这个搞完,dis_value是0? // 因为csb_speed是0? // 但是csb_speed为什么是0? // 为什么超声波的速度由变为0 了? //8 我把超声波的速度设置到340M/S,那么这个时候需要计算了。 // 距离 (厘米)= 时间(定时器计数值/定时器的频率(2.4576MHZ) ) 乘以声波的速度 34000cm/s // 因此 dis_value = 34000 * 计数值/2.4576M // dis_value = 34*time_value/2457/2,最后得出的是距离值 // 看样子时钟问题已经解决了 // 看样子定时器已经解决了。 // 其实定时器就是+1 的计数速度 //9 现在定时器先这样吧,接下来解决的是超声波问题 // 首先超声波发送是否OK?? dis_value += ((timer_value*csb_speed)/2257)/2; } dis_value = dis_value/5; } /* //8 这个函数几个意思? // 计算超声波速度,难道是校准函数,比如误差之类的? // 难道csb_speed就是超声波的速度值? void csbsc() { //1 难道是值太小了,直接被和谐了,算了,直接写个值吧 temper_value=0.0000615*TEMP_REF; csb_speed=0.03314+temper_value; } */ void timer_init() { //1 定时器总共有5个寄存器 // 其中TSC的最后三位是控制总线时钟分频的 // T1SC= 0x46,看来最后三位是6,那就是64分频 T1SC_TSTOP = 1; //1 那么复位会不会清楚T1MOD的值? // 刚才查的会复位计数寄存器和分频,我草,那岂不是分频没意义了。 // 分频之后的分频值是多少,原来是0,那就是不分频了。 //2 时钟频率2.4576M T1SC_TRST = 1; //3 难道定时的值有影响? // 如此说来,没有影响的。 T1SC = 0X40; T1MODH = 0XFF; T1MODL = 0XFF; } //1 首先确定下载引脚是那几个? // 需要 RST据说不接也可以, OSC1, OSC2, IRQ // PTB0 这个就是下载的,还需要PTB1高电平, PTB2低电平, PTB3可选电平 // 尼玛下载个程序怎么都这么麻烦。 // IRQ有两种选择, VTST, VDD // PTB0默认加上拉电阻 // 目前下载的引脚已经决定了 // 这次下载需要9个引脚 //2 接下来决定接线方式 // 先确定,用IRQ是那个 // 决定IRQ是用VTST // 那么PTB3 为1,Bus clocke 是2.4576M // 波特率9600 //3 难道以前时钟没看完 // 5V的时候总线时钟是8M // 那么外部晶振应该是多少? // 外接32M 的晶振?? void main() { //1 设置数码管 PA5,第二个数码管的 DDRA = 0X20; DDRB = 0XFF; //2 设置第一个数码管,PTD5,第三个数码管PTD4 // 设置超声波输出PTD2,超声波输入 PTD6 DDRD = 0Xb4; //1 定时器初始化 timer_init(); //CSB_IN=1; CSB_OUT=0; //csbsc(); while(1) { csb_test(); //3 把距离转换成数码管接受的值 //offmsd(); led_display(); } }