ultrasonic_App.c
上传用户:sdjqgc
上传日期:2022-08-06
资源大小:2404k
文件大小:10k
开发平台:

Asm

  1. //========================================================================
  2. // 文件名称: ultrasonic_App.c
  3. // 功能描述: 超声波测距模组V2.0的功能接口函数
  4. // 维护记录: 2006-02-21 V2.0
  5. //========================================================================
  6. #include "SPCE061A.h"
  7. #define LONG_SEND_TIMER 1000 //中距测距时的40KHz信号发射时长
  8. #define LONG_SEND_TIMER2 3000 //中距测距的补充测距时的40KHz信号发射时长
  9. #define LONG_WAIT_DELAY 600 //中距测距的防余波干扰延时时长
  10. #define LONG_WAIT_DELAY2 1500 //中距测距的补充测距时的防余波干扰延时时长
  11. #define LONG_RES_ADD 0x00B0 //中距测距的结果补偿值
  12. #define LONG_RES_ADD2 0x0220 //中距测距的补充测距时的结果补偿值
  13. #define LOW_SEND_TIMER 250 //短距测距时的40KHz信号发射时长
  14. #define LOW_SEND_TIMER2 1000 //短距测距的补充测距时的40KHz信号发射时长
  15. #define LOW_WAIT_DELAY 180 //短距测距的防余波干扰延时时长
  16. #define LOW_WAIT_DELAY2 400 //短距测距的补充测距时的防余波干扰延时时长
  17. #define LOW_RES_ADD 0x0034 //短距测距的结果补偿值
  18. #define LOW_RES_ADD2 0x00B0 //短距测距的补充测距时的结果补偿值
  19. unsigned int Counter_buf; //超声波测距当中,用于保存TimerB计数的变量,相当于时长
  20. unsigned int EXT1_IRQ_flag=0; //外部中断标志变量,用于EXT1的IRQ中断程序和测距程序同步
  21. //========================================================================
  22. // 语法格式: void Initial_ult(void)
  23. // 实现功能: 超声波测距模组的初始化子程序
  24. // 参数: 无
  25. // 返回值: 无
  26. //========================================================================
  27. void Initial_ult(void)
  28. {
  29. unsigned int uiTemp;
  30. // 初始化端口主要是IOB8和IOB9
  31. uiTemp = *P_IOB_Dir;
  32. uiTemp = uiTemp|0x0200;
  33. uiTemp = uiTemp&0xfeff;
  34. *P_IOB_Dir = uiTemp;
  35. uiTemp = *P_IOB_Attrib;
  36. uiTemp = uiTemp|0x0200;
  37. uiTemp = uiTemp&0xfeff;
  38. *P_IOB_Attrib = uiTemp;
  39. uiTemp = *P_IOB_Buffer;
  40. uiTemp = uiTemp|0x0300;
  41. *P_IOB_Data = uiTemp;
  42. }
  43. //========================================================================
  44. // 语法格式: void Delay_ult(unsigned int timers)
  45. // 实现功能: 超声波测距模组的延时子程序
  46. // 参数: unsigned int timers    延时的时长(仅是一个相对量)
  47. // 返回值: 无
  48. //========================================================================
  49. void Delay_ult(unsigned int timers)
  50. {
  51. unsigned int i;
  52. for(i=0;i<timers;i++)
  53. {
  54. __asm("nop");
  55. }
  56. }
  57. //========================================================================
  58. // 语法格式: unsigned int Resoult_ult(unsigned int Counter)
  59. // 实现功能: 超声波测距模组的测距数据处理程序,将TimerB的计数值换算为距离
  60. // 参数: Counter 需要换算的计数值
  61. // 返回值: 计算后的距离,厘米为单位
  62. //========================================================================
  63. unsigned int Resoult_ult(unsigned int Counter)
  64. {
  65. unsigned int uiTemp;
  66. unsigned long ulTemp;
  67. ulTemp = (unsigned long)Counter*33500;
  68. ulTemp = ulTemp/196608;
  69.     ulTemp = ulTemp>>1; //除二
  70. uiTemp = (unsigned int)ulTemp;
  71. return uiTemp;
  72. }
  73. //========================================================================
  74. // 语法格式: unsigned int measure_ult(unsigned int type)
  75. // 实现功能: 超声波测距模组的测距程序,完成一次测距
  76. // 参数: type 选择测距类型,
  77. // type=1 中距测距
  78. // type=0 短距测距
  79. // 返回值: 所测得的距离,以厘米为单位
  80. //========================================================================
  81. unsigned int measure2_ult(unsigned int type);
  82. unsigned int measure_ult(unsigned int type)
  83. {
  84. unsigned int Exit_flag = 1;
  85. unsigned int uiTemp;
  86. unsigned int uiResoult;
  87. unsigned int uiSend_Timer,uiWait_Timer,uiRes_Add;
  88. unsigned int uiSystem_Clock;
  89. uiSystem_Clock = *P_SystemClock; //将当前的系统时钟设置暂时保存起来
  90. *P_SystemClock = 0x0088; //将系统时钟设置为49MHz,分频比为1,强振模式
  91. if(type) //根据type即测距类型,选择不同的测距参数
  92. {
  93. uiSend_Timer = LONG_SEND_TIMER;
  94. uiWait_Timer = LONG_WAIT_DELAY;
  95. uiRes_Add = LONG_RES_ADD;
  96. }
  97. else
  98. {
  99. uiSend_Timer = LOW_SEND_TIMER;
  100. uiWait_Timer = LOW_WAIT_DELAY;
  101. uiRes_Add = LOW_RES_ADD;
  102. }
  103. *P_TimerB_Data = 0xfed2;
  104. *P_TimerB_Ctrl = 0x03c0; //enable 40KHz out
  105. Delay_ult(uiSend_Timer); //delay for send the signal
  106. *P_TimerB_Ctrl = 0x0006; //stop 40KHz out
  107. *P_TimerB_Data = 0x0000;
  108. *P_TimerB_Ctrl = 0x0001; //TimerB work as a counter at 192KHz
  109. while(*P_TimerB_Data<uiWait_Timer) //等待一定时间后再打开TimerA的计数(来源于EXT1)
  110. { //以避开余波的干扰
  111. *P_Watchdog_Clear = 0x0001;
  112. }
  113. *P_INT_Clear = 0x0100; //开中断前先清中断
  114. *P_INT_Ctrl = *P_INT_Ctrl_New|0x0100;
  115. *P_INT_Clear = 0xffff; //清除中断发生标志
  116. __asm("IRQ ON"); //打开总中断使能
  117. EXT1_IRQ_flag = 0; //TimerA的溢出中断的标志变量置0
  118. while(Exit_flag)
  119. {
  120. if(EXT1_IRQ_flag==1) //当该变量在timerA的FIQ中断中被置1时表示接收到了回波
  121. {
  122. Exit_flag = 0; //exit
  123. Counter_buf = Counter_buf+uiRes_Add;//计数值加上一定的调整数据
  124. uiResoult = Resoult_ult(Counter_buf);//对计数值进行处理,得出距离值
  125. }
  126. if(*P_TimerB_Data>10000) //如计数值大于10000,表示超时
  127. {
  128. Exit_flag = 0; //exit
  129. uiResoult = measure2_ult(type);//再进行一次补充的测距,将会加长40KHz信号发射的量
  130. *P_TimerB_Ctrl = 0x0006; //stop timerB
  131. }
  132. uiTemp = *P_TimerB_Data;
  133. *P_Watchdog_Clear = 0x0001;
  134. }
  135. *P_INT_Ctrl = *P_INT_Ctrl_New&(~0x0100); //关掉外部中断
  136. __asm("IRQ OFF"); //关掉总中断
  137. *P_SystemClock = uiSystem_Clock; //恢复系统时钟的设置
  138. return uiResoult;
  139. }
  140. //========================================================================
  141. // 语法格式: void EXT1_IRQ_ult(void)
  142. // 实现功能: 超声波测距模组的测距程序的EXT1中断服务程序,在EXT1的IRQ中断
  143. // 中调用
  144. // 参数: 无
  145. // 返回值: 无
  146. //========================================================================
  147. void EXT1_IRQ_ult(void)
  148. {
  149. Counter_buf = *P_TimerB_Data; //save the timerB counter
  150. *P_TimerB_Ctrl = 0x0006; //stop timerB
  151. *P_INT_Ctrl = *P_INT_Ctrl_New&(~0x0100); //关掉外部中断
  152. *P_INT_Clear = 0xffff; //清除中断发生标志
  153. EXT1_IRQ_flag = 1; //通知测距程序,外部中断已发生
  154. }
  155. //========================================================================
  156. // 语法格式: unsigned int measure2_ult(void)
  157. // 实现功能: 补充进行一次远距的测量,以保证能够获取测量结果
  158. // 参数: type 选择测距类型,
  159. // type=1 中距测距
  160. // type=0 短距测距
  161. // 返回值: 所测得的距离,以厘米为单位
  162. //========================================================================
  163. unsigned int measure2_ult(unsigned int type)
  164. {
  165. unsigned int Exit_flag = 1;
  166. unsigned int uiResoult;
  167. unsigned int uiSend_Timer,uiWait_Timer,uiRes_Add;
  168. *P_TimerA_Ctrl = 0x0006; //stop TimerA
  169. *P_INT_Ctrl = *P_INT_Ctrl_New&(~0x0100); //关掉外部中断
  170. __asm("IRQ OFF"); //关掉总中断
  171. *P_INT_Clear = 0xffff; //清除掉中断发生标志
  172. if(type) //根据type即测距类型,选择不同的测距参数
  173. {
  174. uiSend_Timer = LONG_SEND_TIMER2;
  175. uiWait_Timer = LONG_WAIT_DELAY2;
  176. uiRes_Add = LONG_RES_ADD2;
  177. }
  178. else
  179. {
  180. uiSend_Timer = LOW_SEND_TIMER2;
  181. uiWait_Timer = LOW_WAIT_DELAY2;
  182. uiRes_Add = LOW_RES_ADD2;
  183. }
  184. *P_TimerB_Data = 0xfed2;
  185. *P_TimerB_Ctrl = 0x03c0; //enable 40KHz out
  186. Delay_ult(uiSend_Timer); //delay for send the signal
  187. *P_TimerB_Ctrl = 0x0006; //stop 40KHz out
  188. *P_TimerB_Data = 0x0000;
  189. *P_TimerB_Ctrl = 0x0001; //TimerB work as a counter at 192KHz
  190. while(*P_TimerB_Data<uiWait_Timer) //等待一定时间,以避开余波的干扰
  191. {
  192. *P_Watchdog_Clear = 0x0001;
  193. }
  194. *P_INT_Ctrl = *P_INT_Ctrl_New|0x0100;//打开外部中断
  195. *P_INT_Clear = 0xffff; //清除中断发生标志
  196. __asm("IRQ ON"); //打开总中断使能
  197. EXT1_IRQ_flag = 0; //TimerA的溢出中断的标志变量置0
  198. while(Exit_flag)
  199. {
  200. if(EXT1_IRQ_flag==1) //当该变量在timerA的FIQ中断中被置1时表示接收到了回波
  201. {
  202. Exit_flag = 0; //exit
  203. Counter_buf = Counter_buf+uiRes_Add;//计数值加上一定的调整数据
  204. uiResoult = Resoult_ult(Counter_buf);//对计数值进行处理,得出距离值
  205. }
  206. if(*P_TimerB_Data>10000) //如计数值大于10000,表示超时
  207. {
  208. Exit_flag = 0; //exit
  209. uiResoult = 0; //error return data 0
  210. *P_TimerB_Ctrl = 0x0006; //stop timerB
  211. }
  212. }
  213. return uiResoult;
  214. }
  215. //========================================================================
  216. // 语法格式: unsigned int measure_Times(unsigned int type)
  217. // 实现功能: 组合进行共6次的测距程序,包括对6次测量结果的取平均值处理
  218. // 参数: type 选择测距类型,
  219. // type=1 中距测距
  220. // type=0 短距测距
  221. // 返回值: 所测得的距离,以厘米为单位
  222. //========================================================================
  223. unsigned int measure_Times(unsigned int type)
  224. {
  225. unsigned int uiResoult=0,uiMeasure_Index=0,i;
  226. unsigned int uiTemp_buf[6],uiTemp;
  227. unsigned int uiSystem_Clock;
  228. for(;uiMeasure_Index<6;uiMeasure_Index++)
  229. { //循环进行四次测量
  230. uiTemp = measure_ult(type); //进行一次测量,测量类型由type决定
  231. if(uiMeasure_Index==0) //如果为本次测量的第一次测距,则直接保存在缓冲区第一个单元
  232. uiTemp_buf[0] = uiTemp;
  233. else
  234. { //否,则对结果进行比较,进行排序,从大到小排
  235. i = uiMeasure_Index;
  236. while(i) //以下为排序的代码
  237. {
  238. if(uiTemp>uiTemp_buf[i-1])
  239. {
  240. uiTemp_buf[i] = uiTemp_buf[i-1];
  241. uiTemp_buf[i-1] = uiTemp;
  242. }
  243. else
  244. {
  245. uiTemp_buf[i] = uiTemp;
  246. break; //退出排序
  247. }
  248. i--;
  249. }
  250. }
  251. //两次测量之间的延时等待,利用以下代码软仿真时的cycles数结合设置的CPUCLK进行计算,大概72ms
  252. uiSystem_Clock = *P_SystemClock; //将之前的系统时钟的设置用变量保存
  253. *P_SystemClock = 0x000b; //设置为FSYS=24.576MHz  分频比为8
  254. for(i=0;i<5;i++)
  255. {
  256. Delay_ult(1000); //调用延时程序
  257. *P_Watchdog_Clear = 0x0001;
  258. }
  259. *P_SystemClock = uiSystem_Clock; //恢复系统时钟设置
  260. //此处延时结束
  261. }
  262. //对6次测距的结果进行处理
  263. if(uiTemp_buf[5]==0)
  264. { //如果缓冲区中的最小的测距值为0,则采用中间4个数据进行平均
  265. uiResoult = uiTemp_buf[1]+uiTemp_buf[2]+uiTemp_buf[3]+uiTemp_buf[4];
  266. uiResoult = uiResoult/4;
  267. }
  268. else
  269. { //否则就取后5个数据进行平均
  270. uiResoult = uiTemp_buf[1]+uiTemp_buf[2]+uiTemp_buf[3]+uiTemp_buf[4]+uiTemp_buf[5];
  271. uiResoult = uiResoult/5;
  272. }
  273. return uiResoult;
  274. }