【MCU方案】+基于msp430f149实现楼宇对讲系统

2019-07-26 15:36发布

本帖最后由 uestc_zyd 于 2015-6-26 13:14 编辑

一、功能介绍
楼宇对讲系统应用于智能小区。整个系统由门口主机、楼层译码器和室内分机组成。门口主机接收用户输入数据、呼叫处理和控制电控锁。整个系统采用总线方式布线,门口主机到楼层译码器采用3总线方式,楼层译码器到室内分机采用无极性的2总线方式,保证即使用户线短路也不会影响整个系统。
主机发出编码信息(如房间号码),楼层译码器根据接收到的数据进行译码,若为本层的某个房间则将分机接通,主机检测到线路状态后就可以发送振铃信号,分机应答后可以进行通话,并给出开锁信号,即主机在收到分机的开锁信号后会打开电控锁。
二、方案描述
硬件系统包括3个部分:主机、楼层译码器、分机。软件系统主要包括显示模块、存储器操作模块、键盘输入模块、拨号处理模块、主处理模块。
系统构成如下图:

1、硬件主机设计
主机主要包括键盘输入电路、存储器电路、逻辑控制电路、比较器电路、驱动电路和音频处理电路。键盘输入电路主要用于接收用户输入的数据,如密码设置、振铃时间设置、房间号码设置等。存储器电路主要用于存储系统信息,如房间模式、密码。逻辑控制电路主要产生某些逻辑控制信号,如开锁信号、对话信号、振铃信号。比较器电路用于判断分机的状态,如摘机、挂机等。音频电路主要实现对讲功能。
2、楼层译码器设计
用来接收主机发出的编码数据,并对接收到的编码数据,并对接收到的编码数据进行处理,如果是本楼的分机则接通被呼叫的分机。楼层译码器选用HT12D芯片实现。主机发出的编码数据经过HT12D芯片译码,如果编码数据中的地址部分正好和该译码器的地址相同,那么HT12D芯片就在D8/D9/D10/D11中的某一个管脚输出高电平,通过这个高电平来接通分机。

3、软件部分在下节中介绍
三、软件部分
1、显示模块
显示程序是通过P1.2管脚模拟移位时钟信号,P1.0管脚在输出时钟的控制下一位一位地输出数据,P1.1管脚给出锁存信号将数据显示出来。整个显示程序主要由端口初始化、管脚高低电平产生、数据串行输出3个部分组成。

  1. #include <msp430x14x.h>
  2. #include "led.h"

  3. void Init_Port(void)
  4. {
  5. //将P1口所有的管脚在初始化的时候设置为输入方式
  6. P1DIR = 0;
  7. //将P1口所有的管脚设置为一般I/O口
  8. P1SEL = 0;

  9. // 将P1.0 P1.1 P1.2 设置为输出方向
  10. P1DIR |= BIT0;
  11. P1DIR |= BIT1;
  12. P1DIR |= BIT2;
  13. // 将P1.3 P1.4 P1.5 设置为输出方向
  14. P1DIR |= BIT3;
  15. P1DIR |= BIT4;
  16. P1DIR |= BIT5;

  17. //将P2口所有的管脚在初始化的时候设置为输入方式
  18. P2DIR = 0;
  19. //将P2口所有的管脚设置为一般I/O口
  20. P2SEL = 0;
  21. //将中断寄存器清零
  22. P2IE = 0;
  23. P2IES = 0;
  24. P2IFG = 0;
  25. //管脚 P2.0 使能中断
  26. P2IE |= BIT0;
  27. //对应的管脚由低到高电平跳变使相应的标志置位
  28. P2IES &= ~(BIT0);
  29. return;
  30. }
  31. void SHCLK_Hi(void)
  32. {
  33. //P1.2管脚输出高电平
  34. P1OUT |= BIT2;
  35. return;
  36. }
  37. void SHCLK_Lo(void)
  38. {
  39. //P1.2管脚输出低电平
  40. P1OUT &= ~(BIT2);
  41. return;
  42. }
  43. void STCLK_Hi(void)
  44. {
  45. //P1.1管脚输出高电平
  46. P1OUT |= BIT1;
  47. return;
  48. }
  49. void STCLK_Lo(void)
  50. {
  51. //P1.1管脚输出低电平
  52. P1OUT &= ~(BIT1);
  53. return;
  54. }
  55. void DataOut(unsigned char nValue)
  56. {
  57. int i;
  58. int j;
  59. for(i = 0;i < 8;i++)
  60. {
  61. if ((nValue & 0x01) == 1)
  62. {
  63. P1OUT |= BIT0;//输出高电平
  64. }
  65. else
  66. {
  67. P1OUT &= ~(BIT0);//输出低电平
  68. }
  69. SHCLK_Hi();//时钟高电平,上升沿有效
  70. for(j = 10; j > 0; j--) ;//延迟一点时间
  71. SHCLK_Lo();//时钟低电平
  72. for(j = 10; j > 0; j--) ;
  73. nValue >>= 1;
  74. }
  75. return;
  76. }


  77. void Init_CLK(void)
  78. {
  79. unsigned int i;
  80. //将寄存器的内容清零
  81. //XT2震荡器开启
  82. //LFTX1工作在低频模式
  83. //ACLK的分频因子为1
  84. BCSCTL1 = 0X00;

  85. do
  86. {
  87. // 清除OSCFault标志
  88. IFG1 &= ~OFIFG;
  89. for (i = 0x20; i > 0; i--);
  90. }
  91. while ((IFG1 & OFIFG) == OFIFG); // 如果OSCFault =1

  92. //将寄存器的内容清零
  93. BCSCTL2 = 0X00;
  94. //MCLK的时钟源为TX2CLK,分频因子为1
  95. BCSCTL2 += SELM1;
  96. //SMCLK的时钟源为TX2CLK,分频因子为1
  97. BCSCTL2 += SELS;
  98. }
复制代码
2、I2C模块(存储器操作模块)
采用串行存储器24LC02B通过I2C实现与MSP430的连接。I2C的时序包括起始条件、数据传输、确认、停止条件。
  1. #include "I2C.h"

  2. void I2C_Initial( void )
  3. {
  4. P1DIR |= SCL; //将SCL管脚(P1.3)设置为输出管脚
  5. I2C_Set_sck_low();
  6. I2C_STOP();
  7. Delay_ms(10);
  8. return;
  9. }
  10. void I2C_Set_sda_high( void )
  11. {
  12. P1DIR |= SDA; //将SDA设置为输出模式
  13. P1OUT |= SDA; //SDA管脚输出为高电平

  14. _NOP();
  15. _NOP();
  16. return;
  17. }
  18. void I2C_Set_sda_low ( void )
  19. {
  20. P1DIR |= SDA; //将SDA设置为输出模式
  21. P1OUT &= ~(SDA); //SDA管脚输出为低电平

  22. _NOP();
  23. _NOP();
  24. return;
  25. }
  26. void I2C_Set_sck_high( void )
  27. {
  28. P1DIR |= SCL; //将SCL设置为输出模式
  29. P1OUT |= SCL; //SCL管脚输出为高电平

  30. _NOP();
  31. _NOP();
  32. return;
  33. }
  34. void I2C_Set_sck_low ( void )
  35. {
  36. P1DIR |= SCL; //将SCL设置为输出模式
  37. P1OUT &= ~(SCL); //SCL管脚输出为低电平

  38. _NOP();
  39. _NOP();
  40. return;
  41. }
  42. int I2C_GetACK(void)
  43. {
  44. int nTemp = 0;
  45. int j;

  46. _NOP();
  47. _NOP();
  48. I2C_Set_sck_low();
  49. for(j = 30;j > 0;j--);
  50. P1DIR &= ~(SDA); //将SDA设置为输入方向
  51. //I2C_Set_sda_high();
  52. I2C_Set_sck_high();

  53. for(j = 30;j > 0;j--);
  54. nTemp = (int)(P1IN & SDA); //获得数据

  55. I2C_Set_sck_low();

  56. return (nTemp & SDA);
  57. }
  58. void I2C_SetACK(void)
  59. {
  60. I2C_Set_sck_low();
  61. I2C_Set_sda_low();
  62. I2C_Set_sck_high();
  63. I2C_Set_sck_low();
  64. return;
  65. }
  66. void I2C_SetNAk(void)
  67. {
  68. I2C_Set_sck_low();
  69. I2C_Set_sda_high();
  70. I2C_Set_sck_high();
  71. I2C_Set_sck_low();
  72. return;
  73. }
  74. void I2C_START(void)
  75. {
  76. int i;

  77. I2C_Set_sda_high();
  78. for(i = 5;i > 0;i--);
  79. I2C_Set_sck_high();
  80. for(i = 5;i > 0;i--);
  81. I2C_Set_sda_low();
  82. for(i = 5;i > 0;i--);
  83. I2C_Set_sck_low();
  84. return;
  85. }
  86. void I2C_STOP(void)
  87. {
  88. int i;

  89. I2C_Set_sda_low();
  90. for(i = 5;i > 0;i--);
  91. I2C_Set_sck_low();
  92. for(i = 5;i > 0;i--);
  93. I2C_Set_sck_high();
  94. for(i = 5;i > 0;i--);
  95. I2C_Set_sda_high();
  96. for(i = 5;i > 0;i--);
  97. I2C_Set_sck_low();
  98. Delay_ms(10); //延迟一点时间

  99. return;
  100. }
  101. void I2C_TxByte(int nValue)
  102. {
  103. int i;
  104. int j;

  105. for(i = 0;i < 8;i++)
  106. {
  107. if(nValue & 0x80)
  108. I2C_Set_sda_high();
  109. else
  110. I2C_Set_sda_low();
  111. for(j = 30;j > 0;j--);
  112. I2C_Set_sck_high();
  113. nValue <<= 1;
  114. for(j = 30;j > 0;j--);
  115. I2C_Set_sck_low();
  116. }

  117. return;
  118. }
  119. /////////////////////////////////////////////
  120. // 接收是从 LSB 到 MSB 的顺序
  121. int I2C_RxByte(void)
  122. {
  123. int nTemp = 0;
  124. int i;
  125. int j;

  126. I2C_Set_sda_high();

  127. P1DIR &= ~(SDA); //将SDA管脚设置为输入方向
  128. _NOP();
  129. _NOP();
  130. _NOP();
  131. _NOP();
  132. for(i = 0;i < 8;i++)
  133. {
  134. I2C_Set_sck_high();

  135. if(P1IN & SDA)
  136. {
  137. nTemp |= (0x01 << i);
  138. }
  139. for(j = 30;j > 0;j--);
  140. I2C_Set_sck_low();
  141. }

  142. return nTemp;
  143. }
  144. void I2C_Write(char nAddr,char nValue)
  145. {
  146. int nTemp = 0xA0;//写命令
  147. // 启动数据总线
  148. I2C_START();
  149. // 发送控制字节
  150. I2C_TxByte(nTemp);
  151. // 等待 ACK
  152. nTemp = I2C_GetACK();

  153. // 发送地址字节
  154. I2C_TxByte(nAddr);
  155. // 等待 ACK
  156. nTemp = I2C_GetACK();

  157. // 发送数据字节
  158. I2C_TxByte(nValue);
  159. // 等待 ACK
  160. nTemp = I2C_GetACK();

  161. // 停止总线
  162. I2C_STOP();
  163. return;
  164. }
  165. int PageWrite(char nAddr,char pBuf[])
  166. {
  167. int i;
  168. int nTemp = 0xA0;//写命令
  169. // 启动数据总线
  170. I2C_START();
  171. // 发送控制字节
  172. I2C_TxByte(nTemp);
  173. // 等待 ACK
  174. nTemp = I2C_GetACK();
  175. if(nTemp & BIT3) return 0;

  176. // 发送地址字节
  177. I2C_TxByte(nAddr);
  178. // 等待 ACK
  179. nTemp = I2C_GetACK();
  180. if(nTemp & BIT3) return 0;

  181. // 发送数据字节
  182. for(i = 0; i < 8;i++)
  183. {
  184. I2C_TxByte(pBuf[0]);
  185. // 等待 ACK
  186. nTemp = I2C_GetACK();
  187. if(nTemp & BIT3) return 0;
  188. }

  189. // 停止总线
  190. I2C_STOP();
  191. return (nTemp & SDA);
  192. }
  193. char I2C_Read(int nAddr)
  194. {
  195. int nRes = -1;
  196. //写命令
  197. int nTemp = 0xA0;
  198. // 启动数据总线
  199. I2C_START();
  200. // 发送控制字节
  201. I2C_TxByte(nTemp);
  202. // 等待 ACK
  203. nTemp = I2C_GetACK();

  204. // 发送地址字节
  205. I2C_TxByte(nAddr);
  206. // 等待 ACK
  207. nTemp = I2C_GetACK();

  208. // 启动数据总线
  209. I2C_START();
  210. // 发送控制字节
  211. nTemp = 0xA1;
  212. I2C_TxByte(nTemp);
  213. // 等待 ACK
  214. nTemp = I2C_GetACK();

  215. //读取数据
  216. nRes = I2C_RxByte();

  217. // 停止总线
  218. I2C_STOP();
  219. //成功返回
  220. return nRes;
  221. }
  222. int ReadSeq(char nAddr, char nValue[], int nLen)
  223. {
  224. int i;
  225. //写命令
  226. int nTemp = 0xA0;
  227. // 启动数据总线
  228. I2C_START();
  229. // 发送控制字节
  230. I2C_TxByte(nTemp);
  231. // 等待 ACK
  232. nTemp = I2C_GetACK();
  233. if(nTemp & BIT3) return 0;

  234. // 发送地址字节
  235. I2C_TxByte(nAddr);
  236. // 等待 ACK
  237. nTemp = I2C_GetACK();
  238. if(nTemp & BIT3) return 0;

  239. // 启动数据总线
  240. I2C_START();
  241. // 发送控制字节
  242. nTemp = 0xA1;
  243. I2C_TxByte(nTemp);
  244. // 等待 ACK
  245. nTemp = I2C_GetACK();
  246. if(nTemp & BIT3) return 0;

  247. //读取数据
  248. for(i = 0; i < nLen; i++)
  249. {
  250. //读一个字节数据
  251. nValue[i] = I2C_RxByte();
  252. //发送ACK
  253. I2C_SetACK();
  254. }

  255. // 停止总线
  256. I2C_STOP();
  257. //成功返回
  258. return 1;
  259. }
  260. void Delay_ms(unsigned long nValue)//毫秒为单位,8MHz为主时钟
  261. {
  262. unsigned long nCount;
  263. int i;
  264. unsigned long j;
  265. nCount = 2667;
  266. for(i = nValue;i > 0;i--)
  267. {
  268. for(j = nCount;j > 0;j--);
  269. }
  270. return;
  271. }
  272. void Delay_us(unsigned long nValue)//微秒为单位,8MHz为主时钟
  273. {
  274. int nCount;
  275. int i;
  276. int j;
  277. nCount = 3;
  278. for(i = nValue;i > 0;i--)
  279. {
  280. for(j = nCount;j > 0;j--);
  281. }
  282. return;
  283. }

复制代码3、键盘输入模块
矩阵键盘电路利用MSP430的一般I/O口来进行扩展设计,矩阵键盘有行、列线组成,通过扫描来获取键盘的输入,读取线的状态就可以判断哪个键被按下。
一般IO口方式的程序设计:
  1. #include <msp430x14x.h>

  2. void Delay(void);
  3. int KeyScan(void);
  4. int KeyProcess(void);
  5. void Init_Port(void)
  6. {
  7. //将P1口所有的管脚在初始化的时候设置为输入方式
  8. P1DIR = 0;

  9. //将P1口所有的管脚设置为一般I/O口
  10. P1SEL = 0;

  11. // 将P1.4 P1.5 P1.6 P1.7设置为输出方向
  12. P1DIR |= BIT4;
  13. P1DIR |= BIT5;
  14. P1DIR |= BIT6;
  15. P1DIR |= BIT7;

  16. //先输出低电平
  17. P1OUT = 0x00;
  18. return;
  19. }
  20. int KeyScan(void)
  21. {
  22. int nP10,nP11,nP12,nP13;
  23. int nRes = 0;
  24. for(;;)
  25. {
  26. //读取各个管脚的状态
  27. nP10 = P1IN & BIT0;
  28. nP11 = (P1IN & BIT1) >> 1;
  29. nP12 = (P1IN & BIT2) >> 2;
  30. nP13 = (P1IN & BIT3) >> 3;

  31. //是否有键被按下
  32. if(nP10 == 0 || nP11 == 0 || nP12 == 0 || nP13 == 0)
  33. {
  34. //有键被按下
  35. break;
  36. }

  37. }
  38. Delay(); //延时一点时间,消除抖动
  39. //读取各个管脚的状态
  40. nP10 = P1IN & BIT0;
  41. nP11 = (P1IN & BIT1) >> 1;
  42. nP12 = (P1IN & BIT2) >> 2;
  43. nP13 = (P1IN & BIT3) >> 3;

  44. //是否有键被按下
  45. if(nP10 == 0 || nP11 == 0 || nP12 == 0 || nP13 == 0)
  46. {
  47. //有键被按下,进行键盘输入分析
  48. nRes = KeyProcess();
  49. }
  50. else return -1;//没有输入,为干扰

  51. return nRes;
  52. }
  53. void Delay(void)
  54. {
  55. int i;
  56. for(i = 100;i--;i > 0) ;//延时一点时间
  57. }
  58. int KeyProcess(void)
  59. {
  60. int nRes = 0;
  61. int nP10;
  62. int nP11;
  63. int nP12;
  64. int nP13;
  65. //P1.4输出低电平
  66. P1OUT &= ~(BIT4);
  67. nP10 = P1IN & BIT0;
  68. if (nP10 == 0) nRes = 13;
  69. nP11 = (P1IN & BIT1) >> 1;
  70. if (nP11 == 0) nRes = 14;
  71. nP12 = (P1IN & BIT2) >> 2;
  72. if (nP12 == 0) nRes = 15;
  73. nP13 = (P1IN & BIT3) >> 3;
  74. if (nP13 == 0) nRes = 16;
  75. //P1.5输出低电平
  76. P1OUT &= ~(BIT4);
  77. nP10 = P1IN & BIT0;
  78. if (nP10 == 0) nRes = 9;
  79. nP11 = (P1IN & BIT1) >> 1;
  80. if (nP11 == 0) nRes = 10;
  81. nP12 = (P1IN & BIT2) >> 2;
  82. if (nP12 == 0) nRes = 11;
  83. nP13 = (P1IN & BIT3) >> 3;
  84. if (nP13 == 0) nRes = 12;
  85. //P1.6输出低电平
  86. P1OUT &= ~(BIT4);
  87. nP10 = P1IN & BIT0;
  88. if (nP10 == 0) nRes = 5;
  89. nP11 = (P1IN & BIT1) >> 1;
  90. if (nP11 == 0) nRes = 6;
  91. nP12 = (P1IN & BIT2) >> 2;
  92. if (nP12 == 0) nRes = 7;
  93. nP13 = (P1IN & BIT3) >> 3;
  94. if (nP13 == 0) nRes = 8;
  95. //P1.7输出低电平
  96. P1OUT &= ~(BIT4);
  97. nP10 = P1IN & BIT0;
  98. if (nP10 == 0) nRes = 1;
  99. nP11 = (P1IN & BIT1) >> 1;
  100. if (nP11 == 0) nRes = 2;
  101. nP12 = (P1IN & BIT2) >> 2;
  102. if (nP12 == 0) nRes = 3;
  103. nP13 = (P1IN & BIT3) >> 3;
  104. if (nP13 == 0) nRes = 4;

  105. P1OUT = 0x00;//恢复以前值。

  106. //读取各个管脚的状态
  107. nP10 = P1IN & BIT0;
  108. nP11 = (P1IN & BIT1) >> 1;
  109. nP12 = (P1IN & BIT2) >> 2;
  110. nP13 = (P1IN & BIT3) >> 3;
  111. for(;;)
  112. {
  113. if(nP10 == 1 && nP11 == 1 && nP12 == 1 && nP13 == 1)
  114. {
  115. //等待松开按键
  116. break;
  117. }
  118. }
  119. return nRes;
  120. }
  121. void Init_CLK(void)
  122. {
  123. unsigned int i;
  124. BCSCTL1 = 0X00; //将寄存器的内容清零
  125. //XT2震荡器开启
  126. //LFTX1工作在低频模式
  127. //ACLK的分频因子为1

  128. do
  129. {
  130. IFG1 &= ~OFIFG; // 清除OSCFault标志
  131. for (i = 0x20; i > 0; i--);
  132. }
  133. while ((IFG1 & OFIFG) == OFIFG); // 如果OSCFault =1

  134. BCSCTL2 = 0X00; //将寄存器的内容清零
  135. BCSCTL2 += SELM1; //MCLK的时钟源为TX2CLK,分频因子为1
  136. BCSCTL2 += SELS; //SMCLK的时钟源为TX2CLK,分频因子为1
  137. }
复制代码中断功能方式的程序:
  1. #include <msp430x14x.h>
  2. void Init_Port(void)
  3. {
  4. //将P1口所有的管脚在初始化的时候设置为输入方式
  5. P1DIR = 0;

  6. //将P1口所有的管脚设置为一般I/O口
  7. P1SEL = 0;

  8. // 将P1.4 P1.5 P1.6 P1.7设置为输出方向
  9. P1DIR |= BIT4;
  10. P1DIR |= BIT5;
  11. P1DIR |= BIT6;
  12. P1DIR |= BIT7;

  13. //先输出低电平
  14. P1OUT = 0x00;

  15. // 将中断寄存器清零
  16. P1IE = 0;
  17. P1IES = 0;
  18. P1IFG = 0;
  19. //打开管脚的中断功能
  20. //对应的管脚由高到低电平跳变使相应的标志置位
  21. P1IE |= BIT0;
  22. P1IES |= BIT0;
  23. P1IE |= BIT1;
  24. P1IES |= BIT1;
  25. P1IE |= BIT2;
  26. P1IES |= BIT2;
  27. P1IE |= BIT3;
  28. P1IES |= BIT3;
  29. _EINT();//打开中断
  30. return;
  31. }
  32. void Delay(void)
  33. {
  34. int i;
  35. for(i = 100;i--;i > 0) ;//延时一点时间
  36. }
  37. int KeyProcess(void)
  38. {
  39. int nP10,nP11,nP12,nP13;
  40. int nRes = 0;
  41. //P1.4输出低电平
  42. P1OUT &= ~(BIT4);
  43. nP10 = P1IN & BIT0;
  44. if (nP10 == 0) nRes = 13;
  45. nP11 = P1IN & BIT1;
  46. if (nP11 == 0) nRes = 14;
  47. nP12 = P1IN & BIT2;
  48. if (nP12 == 0) nRes = 15;
  49. nP13 = P1IN & BIT3;
  50. if (nP13 == 0) nRes = 16;
  51. //P1.5输出低电平
  52. P1OUT &= ~(BIT4);
  53. nP10 = P1IN & BIT0;
  54. if (nP10 == 0) nRes = 9;
  55. nP11 = P1IN & BIT1;
  56. if (nP11 == 0) nRes = 10;
  57. nP12 = P1IN & BIT2;
  58. if (nP12 == 0) nRes = 11;
  59. nP13 = P1IN & BIT3;
  60. if (nP13 == 0) nRes = 12;
  61. //P1.6输出低电平
  62. P1OUT &= ~(BIT4);
  63. nP10 = P1IN & BIT0;
  64. if (nP10 == 0) nRes = 5;
  65. nP11 = P1IN & BIT1;
  66. if (nP11 == 0) nRes = 6;
  67. nP12 = P1IN & BIT2;
  68. if (nP12 == 0) nRes = 7;
  69. nP13 = P1IN & BIT3;
  70. if (nP13 == 0) nRes = 8;
  71. //P1.7输出低电平
  72. P1OUT &= ~(BIT4);
  73. nP10 = P1IN & BIT0;
  74. if (nP10 == 0) nRes = 1;
  75. nP11 = P1IN & BIT1;
  76. if (nP11 == 0) nRes = 2;
  77. nP12 = P1IN & BIT2;
  78. if (nP12 == 0) nRes = 3;
  79. nP13 = P1IN & BIT3;
  80. if (nP13 == 0) nRes = 4;

  81. P1OUT = 0x00;//恢复以前值。

  82. //读取各个管脚的状态
  83. nP10 = P1IN & BIT0;
  84. nP11 = P1IN & BIT1;
  85. nP12 = P1IN & BIT2;
  86. nP13 = P1IN & BIT3;
  87. for(;;)
  88. {
  89. if(nP10 == 1 && nP11 == 1 && nP12 == 1 && nP13 == 1)
  90. {
  91. //等待松开按键
  92. break;
  93. }
  94. }
  95. return nRes;
  96. }
  97. // 处理来自端口 1 的中断
  98. interrupt [PORT1_VECTOR] void PORT_ISR(void)
  99. {
  100. Delay();
  101. KeyProcess();
  102. if(P1IFG & BIT0)
  103. {
  104. P1IFG &= ~(BIT0);// 清除中断标志位
  105. }
  106. if(P1IFG & BIT1)
  107. {
  108. P1IFG &= ~(BIT1);// 清除中断标志位
  109. }
  110. if(P1IFG & BIT2)
  111. {
  112. P1IFG &= ~(BIT2);// 清除中断标志位
  113. }
  114. if(P1IFG & BIT3)
  115. {
  116. P1IFG &= ~(BIT3);// 清除中断标志位
  117. }
  118. }
  119. void Init_CLK(void)
  120. {
  121. unsigned int i;
  122. BCSCTL1 = 0X00; //将寄存器的内容清零
  123. //XT2震荡器开启
  124. //LFTX1工作在低频模式
  125. //ACLK的分频因子为1

  126. do
  127. {
  128. IFG1 &= ~OFIFG; // 清除OSCFault标志
  129. for (i = 0x20; i > 0; i--);
  130. }
  131. while ((IFG1 & OFIFG) == OFIFG); // 如果OSCFault =1

  132. BCSCTL2 = 0X00; //将寄存器的内容清零
  133. BCSCTL2 += SELM1; //MCLK的时钟源为TX2CLK,分频因子为1
  134. BCSCTL2 += SELS; //SMCLK的时钟源为TX2CLK,分频因子为1
  135. }
复制代码4、发送编码数据处理
发送的编码数据总共有12位,前8位为地址数据,后4位为数据信息,首先要发送起始信息,然后再将编码数据一位一位地发送。
  1. //发送编码数据
  2. void Send_data(unsigned int numCode) //要发送的数据是numCode
  3. {
  4. int CodeBit;
  5. int SendBit;
  6. int nHigh;
  7. int nLow;
  8. int n;
  9. int i;

  10. nLow = numCode & 0x0f;
  11. nHigh = numCode >> 4;

  12. Send_Pre();
  13. for(i = 0;i < 8;i++)
  14. {
  15. SendBit = nHigh & 0x01;
  16. if(SendBit == 1)
  17. Send_Bit1();
  18. else
  19. Send_Bit0();
  20. nHigh >>= 1;
  21. }
  22. for(i = 0;i < 4;i++)
  23. {
  24. SendBit = nLow & 0x01;
  25. if(SendBit == 1)
  26. Send_Bit1();
  27. else
  28. Send_Bit0();
  29. nLow >>= 1;
  30. }
  31. }
复制代码5、拨号处理
拨号处理主要根据线路状态来判断分机状态,并根据分机的不同状态进行相应处理。线路状态的检测是通过比较器输入模块进行处理的。拨号处理的具体程序如下:
  1. void DialAndProcess(void)
  2. {
  3. int i;
  4. int nBit5;
  5. int nBit6;
  6. //判断选通房间分机是否存在
  7. Delay();
  8. Delay();
  9. Delay();
  10. nBit5 = (P1IN & BIT5) >> 5;
  11. nBit6 = (P1IN & BIT6) >> 6;
  12. if((nBit6 == 1) && (nBit5 == 0))
  13. {
  14. //分机存在
  15. //清除锁存信号
  16. STCLK_Lo();
  17. //输出1
  18. DataOut(nLed[1]);
  19. //给锁存信号,显示数据
  20. STCLK_Hi();

  21. //判断分机是否短路
  22. nBit5 = (P1IN & BIT5) >> 5;
  23. nBit6 = (P1IN & BIT6) >> 6;
  24. if((nBit6 == 1) && (nBit5 == 1))
  25. {
  26. //分机短路
  27. //提示音三次
  28. Ring();
  29. P4OUT &= ~(BIT2);
  30. Delay_1s();
  31. Ring();
  32. P4OUT &= ~(BIT2);
  33. Delay_1s();
  34. Ring();
  35. Delay_1s();
  36. P4OUT &= ~(BIT2);
  37. }//分机短路
  38. else
  39. {
  40. //分机不短路
  41. //发出振铃信号
  42. //初始化摘机标志,为0代表没有摘机
  43. ZhaijiFlag = 0;
  44. //定时器中断允许
  45. TBCTL |= TBCLR;
  46. TBCCTL0 |= CCIE;
  47. //在振铃时间30s内
  48. while(RingFlag)
  49. {
  50. //发出振铃信号
  51. Ring();
  52. Delay_1s();
  53. P4OUT &= ~(BIT2);
  54. //判断分机是否摘机
  55. nBit5 = (P1IN & BIT5) >> 5;
  56. nBit6 = (P1IN & BIT6) >> 6;
  57. if((nBit6 == 0) && (nBit5 == 0))
  58. {
  59. //分机摘机
  60. //摘机标志为1,代表摘机
  61. ZhaijiFlag = 1;
  62. }//分机摘机
  63. if(ZhaijiFlag == 1) break;
  64. }//振铃时间内

  65. //定时器中断禁止
  66. TBCCTL0 &= ~(CCIE);

  67. //假如分机摘机
  68. if(ZhaijiFlag == 1)
  69. {
  70. //分机摘机
  71. //对话
  72. //定时器中断允许
  73. TBCTL |= TBCLR;
  74. TBCCTL0 |= CCIE;
  75. P4OUT &= ~(BIT2);
  76. DialogFlag = 1;
  77. //在对话时间60s内
  78. while( DialogFlag)
  79. {
  80. //打开对讲
  81. P4OUT |= BIT0;
  82. P4OUT |= BIT1;
  83. P4OUT &= ~(BIT2);
  84. P4OUT &= ~(BIT4);

  85. //判断分机是否挂机
  86. nBit5 = (P1IN & BIT5) >> 5;
  87. nBit6 = (P1IN & BIT6) >> 6;
  88. if((nBit6 == 0) && (nBit5 == 0))
  89. {
  90. //分机挂机
  91. //关闭对讲
  92. P4OUT &= ~(BIT0);
  93. P4OUT &= ~(BIT3);
  94. }//分机挂机,返回
  95. else
  96. {
  97. //分机没有挂机
  98. //判断是否开锁
  99. nBit5 = (P1IN & BIT5) >> 5;
  100. nBit6 = (P1IN & BIT6) >> 6;
  101. if((nBit6 == 1) && (nBit5 == 1))
  102. {
  103. //分机开锁
  104. for(i = 0;i < 10;i++)
  105. {
  106. //开电锁命令
  107. P4OUT &= ~(BIT1);
  108. }
  109. break;
  110. }//分机开锁
  111. else//不开锁
  112. {
  113. ;
  114. }//不开锁
  115. }//分机没有挂机
  116. }//对话时间内

  117. //定时器中断禁止
  118. TBCCTL0 &= ~(CCIE);
  119. }//分机摘机
  120. }//分机不短路
  121. }//分机存在
  122. else //分机不存在
  123. {
  124. //清除锁存信号
  125. STCLK_Lo();
  126. //输出0
  127. DataOut(nLed[0]);
  128. //给锁存信号,显示数据
  129. STCLK_Hi();

  130. //提示音两次
  131. Ring();
  132. Delay_1s();
  133. Ring();
  134. }

  135. nidle = 1; //重新开始扫描键盘
  136. }
复制代码

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。