发送代码

  1. #include <iocc2530.h>
  2. #include "hal_mcu.h"
  3. #include "hal_assert.h"
  4. #include "hal_board.h"
  5. #include "hal_rf.h"
  6. #include "basic_rf.h"
  7. #include <stdio.h>
  8. #include "usb.h"
  9. #include "12864.h"
  10. #include "oled.h"
  11. //#define RX
  12. uchar Recdata[10];
  13. uchar RXTXflag=1;
  14. uchar str[20] = "RF_text";
  15. uchar temp;
  16. uint datanumber = 0;
  17. unsigned char buf[10];
  18. unsigned char len=0;
  19. unsigned char i;
  20. uint stringlen = 0;
  21. /**********************************
  22. 初始化串口函数
  23. **********************************/
  24. void initUART0(void)
  25. {
  26. CLKCONCMD &= ~0x40; //设置系统时钟源为32MHZ晶振
  27. while (CLKCONSTA & 0x40)
  28. ; //等待晶振稳定
  29. CLKCONCMD &= ~0x47; //设置系统主时钟频率为32MHZ
  30. SLEEPCMD |= 0x04; //关闭其它无用频率信号
  31. PERCFG = 0x00; //位置1P0口
  32. P0SEL |= (1 << 3) | (1 << 2); // P0设置为串口
  33. P2DIR &= ~((1 << 7) | (1 << 6)); // P0优先作为UART0
  34. U0CSR |= (1 << 7);
  35. U0GCR |= 9; //指数值,波特率设为9600
  36. U0BAUD |= 59; //小数部分59
  37. UTX0IF = 1; // usart 0 tx中断
  38. U0CSR |= (1 << 6); //接收器使能
  39. IEN0 |= (1 << 7) | (1 << 2);
  40. }
  41. /*******************
  42. 初始化系统时钟
  43. *******************/
  44. void InitClock(void)
  45. {
  46. CLKCONCMD &= ~0x40; //设置系统时钟源为32MHZ晶振
  47. while (CLKCONSTA & 0x40)
  48. ; //等待晶振稳定
  49. CLKCONCMD &= ~0x47; //设置系统主时钟频率为32MHZ
  50. SLEEPCMD |= 0x04; //关闭其它无用频率信号
  51. }
  52. /*******************
  53. 延时
  54. *******************/
  55. void Delay(unsigned int n)
  56. {
  57. unsigned int tt;
  58. for (tt = 0; tt < n; tt++)
  59. ;
  60. for (tt = 0; tt < n; tt++)
  61. ;
  62. for (tt = 0; tt < n; tt++)
  63. ;
  64. for (tt = 0; tt < n; tt++)
  65. ;
  66. for (tt = 0; tt < n; tt++)
  67. ;
  68. }
  69. /****************************************************************
  70. 串口接收一个字符:一旦有数据从串口传至CC2530,则进入中断,将接收到的数据赋值给变量temp.
  71. ****************************************************************/
  72. #pragma vector = URX0_VECTOR
  73. __interrupt void UART0_ISR(void)
  74. {
  75. URX0IF = 0;//清中断标志
  76. //Recdata[datanumber++] = U0DBUF;//U0DBUF:USART 0 接收/发送数据缓存
  77. temp= U0DBUF;
  78. }
  79. //RF中断初始化
  80. void rf_init()
  81. {
  82. //(1 << 6)硬件产生一个CRC-16(ITU-T)并附加到发送帧。不需要写最后2 个字节到TXBUF。
  83. //硬件检查一个CRC-16,并以一个16 位状态字代替RX FIFO,包括一个CRC OK 位。状态字可通过APPEND_DATA_MODE 控制。
  84. //(1 << 5)定义无线电是否自动发送确认帧。当autoack 使能,所有经过地址过滤接受的帧都设置确认请求标志,在接收之后自动确认一个有效的CRC12 符号周期。
  85. FRMCTRL0 |= (1 << 5) | (1 << 6); //(0x20 | 0x40);//硬件CRC以及AUTO_ACK使能 FRMCTRL0:帧处理
  86. TXFILTCFG = 0x09; //0000 1001 设置TX抗混叠过滤器以获得合适的带宽
  87. AGCCTRL1 = 0x15; //调整AGC目标值
  88. FSCAL1 = 0x00; //获得最佳的EVM
  89. RFIRQM0 |= (1 << 6); // RXPKTDONE 中断位使能
  90. IEN2 |= (1 << 0); // RF 中断使能
  91. EA = 1; //开中断
  92. FREQCTRL = 0x0a; //信道选择,选择11信道
  93. SHORT_ADDR0 = 0x05; // 0x0005//目标地址过滤期间使用的短地址
  94. SHORT_ADDR1 = 0x00;
  95. PAN_ID0 = 0x23; // 选择两个设备进行无线通信时的个域网ID: PANID 0x0022//目标地址过滤期间使用的PANID
  96. PAN_ID1 = 0x00;
  97. RFST = 0xed; //清除RXFIFO缓冲区并复位解调器
  98. RFST = 0xe3; //为RX使能并校准频率合成器
  99. FRMFILT0 &= ~(1 << 0); //禁止帧过滤
  100. }
  101. //通信
  102. void tx()
  103. {
  104. unsigned char i;
  105. RFST = 0xe3; //为RX使能并校准频率合成器
  106. while (FSMSTAT1 & ((1 << 1) | (1 << 5)));// 等待发送状态不活跃并且没有接收到SFD
  107. RFIRQM0 &= ~(1 << 6); //禁止RXPKTDONE接收数据包中断
  108. IEN2 &= ~(1 << 0); //禁止RF中断
  109. RFST = 0xee; // 清除TXFIFO缓存
  110. RFIRQF1 = ~(1 << 1); // 清除 TXDONE 发送完成中断
  111. if (Recdata[7]=='N')
  112. {
  113. RFD = 8 + 2; // 发送的第一个字节是传输的帧长度
  114. for (i = 0; i < 8 + 2; i++) //将mac的内容写到RFD中
  115. RFD = Recdata[i];
  116. }
  117. else
  118. {
  119. RFD = 9 + 2; // 发送的第一个字节是传输的帧长度
  120. for (i = 0; i < 9 + 2; i++) //将mac的内容写到RFD中
  121. RFD = Recdata[i];
  122. }
  123. RFST = 0xe9; //校准后使能TX
  124. while (!(RFIRQF1 & (1 << 1)));//等待传输结束
  125. RFIRQF1 = ~(1 << 1); //清除 TXDONE状态
  126. RFIRQM0 |= (1 << 6); // 打开RX中断
  127. IEN2 |= (1 << 0); //打开RF中断
  128. }
  129. //接收中断处理
  130. #pragma vector = RF_VECTOR
  131. __interrupt void rf_isr(void)
  132. {
  133. unsigned char i;
  134. //关中断
  135. IEN2 &= ~0X01;
  136. //接收帧结束
  137. if (RFIRQF0 & (1 << 6))
  138. {
  139. len = RFD; //接收帧长度
  140. len &= 0x7f;
  141. for (i = 0; i < len; i++) //将接收的数据写入buf中
  142. {
  143. buf[i] = RFD;
  144. Delay(200);
  145. }
  146. S1CON = 0;// 清RF中断
  147. RFIRQF0 &= ~(1 << 6);//清RXPKTDONE中断
  148. led1 = ~led1;//LED1等状态改变
  149. //设置断点后,程序停止在断点处,但RF仍旧在接收,导致FIFO溢出,无法接收数据,继续运行后再也无法接收。所以要运行一下指令
  150. RFST = 0xed; //清除RXFIFO缓冲区并复位解调器
  151. }
  152. IEN2 |= (1 << 0);
  153. }
  154. void main(void)
  155. {
  156. P0DIR |= 0x73;
  157. OLED_Init();//初始化OLED
  158. OLED_Clear();
  159. #if NODE_TYPE
  160. OLED_ShowString(30,1,"SEND_ADDR");//发送数据
  161. #else
  162. OLED_ShowString(30,1,"RECV_ADDR ");//接收数据
  163. #endif
  164. Led_Init();//初始化LED
  165. P1DIR = 0x03;//P1控制LED
  166. initUART0();//初始化串口0函数
  167. UartTX_Send_String(str,20);
  168. while(1){
  169. if(RXTXflag == 1){
  170. if(temp!=0){
  171. if((temp != '#') && (datanumber < 9)){
  172. Recdata[datanumber++] = temp;
  173. }else{
  174. RXTXflag = 3;
  175. Recdata[datanumber++] = '\0';
  176. }
  177. temp = 0;
  178. }
  179. }
  180. if(RXTXflag == 3){
  181. U0CSR &= ~(1<<6);// 不能接收
  182. if(Recdata[7]=='N'){
  183. //显示OLED
  184. led1=0;
  185. UartTX_Send_String(Recdata,datanumber);
  186. P0DIR |= 0x73;
  187. //Recdata[8]=0;
  188. OLED_Init();//初始化OLED
  189. OLED_Clear();
  190. OLED_ShowString(30,1,"SEND_ADDR");
  191. OLED_ShowString(30,3,"MUSIC_ON ");
  192. rf_init();
  193. tx();
  194. Delay(2000); //延时
  195. }else if(Recdata[7]=='F'){
  196. led1=1;
  197. UartTX_Send_String(Recdata,datanumber);
  198. P0DIR |= 0x73;
  199. OLED_Init();//初始化OLED
  200. OLED_Clear();
  201. OLED_ShowString(30,1,"SEND_ADDR");
  202. OLED_ShowString(30,3,"MUSIC_OFF");
  203. rf_init();
  204. tx();
  205. Delay(2000); //延时
  206. }
  207. U0CSR |= (1<<6);//0x40允许接收
  208. RXTXflag = 1;
  209. datanumber = 0;
  210. }
  211. }
  212. }

接受代码

  1. #include "ioCC2530.h"
  2. #include "oled.h"
  3. #include <string.h>
  4. #include "type.h"
  5. #define RX
  6. #define JIEPAI 125 // us
  7. unsigned char buf[128];
  8. unsigned char len = 0;
  9. unsigned char i;
  10. uchar str1[8] = "ready.";
  11. char Recdata[20];
  12. uchar RXTXflag = 1;
  13. uchar temp;
  14. uint datanum = 0;
  15. uint stringlen = 0;
  16. //播放音乐模块
  17. unsigned char yuepu_cnt = 0; //乐谱数组计数
  18. unsigned char k = 0;
  19. unsigned int jiepai_cnt = 0;
  20. unsigned char sszymmh[] = { //乐谱数组 (音符,音高,节拍)
  21. // 凉凉
  22. 6, 0, 2, 3, 1, 2, 3, 1, 2, 2, 1, 2, 3, 1, 2, 5, 1, 2, 3, 1, 2,
  23. 2, 1, 2, 3, 1, 4, 6, 0, 8, 7, 0, 2, 7, 0, 2, 7, 0, 2, 1, 1, 2,
  24. 7, 0, 4, 3, 0, 2, 5, 0, 2, 6, 0, 2, 5, 0, 10,
  25. 6, 0, 2, 3, 1, 2, 3, 1, 2, 2, 1, 2, 3, 1, 2, 2, 1, 2, 3, 1, 2,
  26. 5, 1, 4, 3, 1, 4, 2, 1, 2, 3, 1, 2, 5, 1, 2, 5, 1, 4, 6, 1, 4,
  27. 6, 1, 4, 5, 1, 4, 5, 1, 2, 6, 1, 10};
  28. unsigned int YINFU[] = { //音符数组
  29. // 低音 0
  30. 0X1DD2, 0X1A94, 0X17AD, 0X1663, 0X13EE, 0X11C1, 0X0FD1,
  31. //中音 1
  32. 0x0EF0, 0X0D4F, 0X0BDB, 0X0B31, 0X09F7, 0X08E1, 0X07E8,
  33. //高音 2
  34. 0X1912, 0X06A6, 0X05ED, 0X0598, 0X04FC, 0X0470, 0X03F9};
  35. //初始化函数声明
  36. void Init_Sys(void)
  37. {
  38. CLKCONCMD &= ~0x7f; //晶振设置为32MHZ
  39. while (CLKCONSTA & 0x40)
  40. ; //等待晶振稳定
  41. P1SEL &= ~((1 << 0) | (1 << 1));
  42. P1DIR |= (1 << 0) | (1 << 1);
  43. P2SEL &= ~(1 << 0); // P2_0通用I/O
  44. P2DIR |= (1 << 0); //输出
  45. beep = 0; //初始低电平 不叫
  46. led1 = 0;
  47. led2 = 1;
  48. }
  49. void Init_T1(void) //系统工作频率32MHz,定时器1工作频率4MHz(8分频)
  50. {
  51. T1CCTL0 = (1 << 2) | (1 << 6); //通道0终端使能,比较模式
  52. T1CTL = (1 << 2) | (2 << 0); //启动,设8分频,设模模式,1/4Mhz(0.25ms)
  53. T1IE = 1; //开T1中断
  54. }
  55. void Init_T3(void) //系统工作频率32MHz,定时器3工作频率1MHz(32分频)
  56. {
  57. T3CC0 = JIEPAI; //定时器3比较模式模为125us
  58. jiepai_cnt = 0;
  59. T3CCTL0 = (1 << 2) | (1 << 6); //通道0终端使能,比较模式
  60. T3CTL = (5 << 5) | (1 << 4) | (1 << 2) | (2 << 0); //设32分频,启动定时器,复位T3计数器,设模模式
  61. T3IE = 1; //开T3中断
  62. }
  63. void delay_jiepai(void)
  64. {
  65. jiepai_cnt = 0;
  66. T3CTL |= (1 << 2) | (1 << 4); //复位并启动T3计数器
  67. T3CC0 = JIEPAI;
  68. while (jiepai_cnt != (sszymmh[yuepu_cnt + 2] * 1000))
  69. ;
  70. }
  71. //---------------------------------------------------------------------------------------------------------射频模块-------
  72. /*******************
  73. 初始化系统时钟
  74. *******************/
  75. void InitClock(void)
  76. {
  77. CLKCONCMD &= ~0x40; //设置系统时钟源为32MHZ晶振
  78. while (CLKCONSTA & 0x40)
  79. ; //等待晶振稳定
  80. CLKCONCMD &= ~0x47; //设置系统主时钟频率为32MHZ
  81. SLEEPCMD |= 0x04; //关闭其它无用频率信号
  82. }
  83. /*******************
  84. 延时
  85. *******************/
  86. void Delay(unsigned int n)
  87. {
  88. unsigned int tt;
  89. for (tt = 0; tt < n; tt++)
  90. ;
  91. for (tt = 0; tt < n; tt++)
  92. ;
  93. for (tt = 0; tt < n; tt++)
  94. ;
  95. for (tt = 0; tt < n; tt++)
  96. ;
  97. for (tt = 0; tt < n; tt++)
  98. ;
  99. }
  100. void rf_init()
  101. {
  102. FRMCTRL0 |= (1 << 5) | (1 << 6); //(0x20 | 0x40);//硬件CRC以及AUTO_ACK使能
  103. TXFILTCFG = 0x09; //设置TX抗混叠过滤器以获得合适的带宽
  104. AGCCTRL1 = 0x15; //调整AGC目标值
  105. FSCAL1 = 0x00; //获得最佳的EVM
  106. RFIRQM0 |= (1 << 6); // RXPKTDONE 中断位使能
  107. IEN2 |= (1 << 0); // RF 中断使能
  108. EA = 1; //开中断
  109. FREQCTRL = 0x0a; //信道选择,选择11信道
  110. SHORT_ADDR0 = 0x05; // 0x0005 //目标地址过滤期间使用的短地址
  111. SHORT_ADDR1 = 0x00;
  112. PAN_ID0 = 0x23; // 0x0022 //目标地址过滤期间使用的PANID
  113. PAN_ID1 = 0x00;
  114. RFST = 0xed; //清除RXFIFO缓冲区并复位解调器
  115. RFST = 0xe3; //为RX使能并校准频率合成器
  116. FRMFILT0 &= ~(1 << 0); //禁止帧过滤
  117. }
  118. //接收中断处理
  119. #pragma vector = RF_VECTOR
  120. __interrupt void rf_isr(void)
  121. {
  122. unsigned char i;
  123. //关中断
  124. IEN2 &= ~0X01;
  125. //接收帧结束
  126. if (RFIRQF0 & (1 << 6))
  127. {
  128. len = RFD; //接收帧长度
  129. len &= 0x7f;
  130. for (i = 0; i < len; i++) //将接收的数据写入buf中
  131. {
  132. buf[i] = RFD;
  133. Delay(200);
  134. }
  135. if (buf[7] == 'N')
  136. {
  137. P0DIR |= 0x73;
  138. OLED_Init(); //初始化OLED
  139. OLED_Clear();
  140. OLED_ShowString(30, 1, "RECV_ADDR");
  141. OLED_ShowString(30, 3, "MUSIC_ON");
  142. delay_ms(250);
  143. //放歌
  144. led1 = 1;
  145. led2 = 0;
  146. Init_Sys();
  147. Init_T1();
  148. k = sszymmh[yuepu_cnt] - 1 + 7 * sszymmh[yuepu_cnt + 1];
  149. Init_T3();
  150. EA = 1; //开总中断
  151. }
  152. else if (buf[7] == 'F')
  153. {
  154. //停止播放
  155. beep = 0;
  156. Delay(2000);
  157. Delay(2000);
  158. Delay(2000);
  159. T1IE = 0;
  160. T3IE = 0;
  161. beep = 0;
  162. jiepai_cnt = 0;
  163. yuepu_cnt = 0;
  164. led1 = 1;
  165. led2 = 1;
  166. // OLED
  167. P0DIR |= 0x73;
  168. OLED_Init(); //初始化OLED
  169. OLED_Clear();
  170. OLED_ShowString(30, 1, "RECV_ADDR");
  171. OLED_ShowString(30, 3, "MUSIC_OFF");
  172. delay_ms(250);
  173. }
  174. S1CON = 0; // 清RF中断
  175. RFIRQF0 &= ~(1 << 6); //清 RXPKTDONE中断
  176. //设置断点后,程序停止在断点处,但RF仍旧在接收,导致FIFO溢出,无法接收数据,继续运行后再也无法接收。所以要运行一下指令
  177. RFST = 0xed; //清除RXFIFO缓冲区并复位解调器
  178. }
  179. IEN2 |= (1 << 0);
  180. }
  181. #pragma vector = T1_VECTOR
  182. __interrupt void T1_ISR(void)
  183. {
  184. if (buf[7] == 'F') //如果是F则
  185. {
  186. beep = 0; //初始低电平 不叫
  187. led1 = 0;
  188. led2 = 0;
  189. yuepu_cnt = 0;
  190. jiepai_cnt = 0;
  191. T1CC0H = 0; //定时器1 通道0 捕获/比较值高字节
  192. T1CC0L = 0; //定时器1 通道1 捕获/比较值低字节
  193. }
  194. else
  195. {
  196. beep = !beep; // 1电平 叫
  197. T1CC0H = YINFU[k] >> 8;
  198. T1CC0L = YINFU[k] & 0xFF;
  199. }
  200. }
  201. #pragma vector = T3_VECTOR
  202. __interrupt void T3_ISR(void)
  203. {
  204. // T3CC0 = JIEPAI;
  205. jiepai_cnt++;
  206. if (jiepai_cnt >= (sszymmh[yuepu_cnt + 2] * 1000)) //节拍数组 1/4 单位:ms
  207. {
  208. jiepai_cnt = 0;
  209. yuepu_cnt += 3;
  210. if (yuepu_cnt >= sizeof(sszymmh))
  211. yuepu_cnt = 0;
  212. k = sszymmh[yuepu_cnt] - 1 + 7 * sszymmh[yuepu_cnt + 1];
  213. T1CC0H = YINFU[k] >> 8;
  214. T1CC0L = YINFU[k] & 0xFF;
  215. led1 = !led1; //播放一个音符交替闪烁
  216. led2 = !led2; //
  217. }
  218. }
  219. int main(void)
  220. {
  221. EA = 0;
  222. InitClock(); //初始化系统时钟
  223. rf_init();
  224. EA = 1;
  225. }

任务

每组两个同学,使用两个IMOTE CC2530 无线通信节点板(无线发送端/接收端节点)与PC机。具体任务如下:
PC机通过串口通信软件向无线发送端节点的单片机发送字符串”MUSIC_ON”或”MUSIC_OFF”。
无线发送端节点:无线发送端单片机节点接收到PC机发送的字符串后在OLED显示屏上显示字符串内容,同时通过无线RF向无线接收端节点发送字符串数据。
无线发接收端节点:无线发接收端节点接收通过无线RF方式发送的字符数据,在OLED显示屏上显示字符串内容,并播放或停止播放音乐。

OLED

功能引脚 描述
VCC 3.3V/5V电源正
GND 电源地
NC NC
DIN SPI数据输入
CLK SPI时钟输入
CS 片选,低电平有效
RST 复位

GND:电源地
VCC:2.2V~5.5V
SCL(D0):CLK 时钟(高电平2.2V~5.5V)
SDA(D1):MOSI 数据(高电平2.2V~5.5V)
RST:复位(高电平2.2V~5.5V)
D/C:数据/命令(高电平2.2V~5.5V)
image.png
image.png