12下一页
返回列表 发新帖我要提问本帖赏金: 10.00元(功能说明)

[PIC®/AVR®/dsPIC®产品] 为了遥控的更远,我用PIC18F16Q41驱动CC1101收发数据

[复制链接]
6202|26
 楼主| gaoyang9992006 发表于 2021-11-19 21:39 | 显示全部楼层 |阅读模式
本帖最后由 gaoyang9992006 于 2021-11-19 21:42 编辑

#技术资源# #申请原创# @21小跑堂
之前我做了蓝牙遥控的小车,这里为了拓展遥控的距离,我准备采用CC1101模块进行拓展距离。
我之所以选择PIC或AVR是出于MCC的快捷可视化配置,让我不用去了解单片机的寄存器即可轻松快速实现设计目标。

端口的配置上我使用MCC进行配置,这样就不需要在移植代码中实现一堆的初始化了,非常方便。
PIC和AVR都具备内部上拉电阻,在需要配置为输入的端口,使用上拉稳定电平是非常容易的。
另外MCC的端口可定制新名字功能,非常有助于我们移植代码,防止多了就容易乱。

在这个表里,非常容易初始化代码,可以设置是否上拉,另外可以指定初始化后是否默认高电平。

利用MCC生成的代码我们直接就可以用于移植了。比如下面的串口收发
  1. /**
  2.   * [url=home.php?mod=space&uid=247401]@brief[/url] :串口发送数据
  3.   * @param :
  4.   *                        @TxBuffer:发送数据首地址
  5.   *                        @Length:数据长度
  6.   * [url=home.php?mod=space&uid=536309]@NOTE[/url]  :无
  7.   * @retval:无
  8.   */
  9. void drv_uart_tx_bytes( uint8_t* TxBuffer, uint8_t Length )
  10. {
  11.         while( Length-- )
  12.         {
  13.                 UART1_Write(*TxBuffer);
  14.                 TxBuffer++;
  15.         }
  16. }

  17. /**
  18.   * [url=home.php?mod=space&uid=247401]@brief[/url] :串口接收数据
  19.   * @param :
  20.   *                        @RxBuffer:发送数据首地址
  21.   * [url=home.php?mod=space&uid=536309]@NOTE[/url]  :无
  22.   * @retval:接收到的字节个数
  23.   */
  24. uint8_t drv_uart_rx_bytes( uint8_t* RxBuffer )
  25. {
  26.         uint8_t l_RxLength = 0;
  27.         uint16_t l_UartRxTimOut = 0x7FFF;
  28.         
  29.         while( l_UartRxTimOut-- )                        //等待查询串口数据
  30.         {

  31.                 if( UART1_is_rx_ready())
  32.                 {
  33.             *RxBuffer = UART1_Read();
  34.             RxBuffer++;
  35.             l_RxLength++;
  36.                         l_UartRxTimOut = 0x7FFF;        //接收到一个字符,回复等待时间
  37.                 }
  38.                 if( 100 == l_RxLength )
  39.                 {
  40.                         break;                        //不能超过100个字节
  41.                 }
  42.         }
  43.         
  44.         return l_RxLength;                                        //等待超时,数据接收完成
  45. }
以及SPI的端口操作映射,只需要在对应的头文件修改成MCC生成的代码即可
  1. #define __USE_SOFT_SPI_INTERFACE__


  2. #define spi_set_nss_high( )                        NSS_SetHigh()                                         //片选置高
  3. #define spi_set_nss_low( )                        NSS_SetLow()        //片选置低


  4. #ifdef __USE_SOFT_SPI_INTERFACE__                        /** 只有使用软件SPI才需要的封装 */               


  5. #define spi_set_clk_high( )                        SCL_SetHigh()                                        //时钟置高
  6. #define spi_set_clk_low( )                        SCL_SetLow()         //时钟置低

  7. #define spi_set_mosi_hight( )                MOSI_SetHigh()                                        //发送脚置高
  8. #define spi_set_mosi_low( )                        MOSI_SetLow()        //发送脚置低

  9. #define spi_get_miso( )                                MISO_GetValue() // 若相应输入位为低则得到0,相应输入位为高则得到1
因为开发板只有一个可配置的LED,所以这里我就只使用了红色的
  1. void drv_led_on( LedPortType LedPort )
  2. {
  3.         if( LED_RED == LedPort )        //LED_RED
  4.         {
  5.                 RED_LED_SetLow();        //红色LED引脚置低,红色LED亮
  6.         }
  7.         else                                                //LED_BLUE
  8.         {
  9.                 ;//绿色LED引脚置低,蓝色LED亮
  10.         }
  11.         
  12. }

  13. /**
  14.   * @brief :LED灭
  15.   * @param :
  16.   *                        @LedPort:LED选择,红色或绿色
  17.   * @note  :无
  18.   * @retval:无
  19.   */
  20. void drv_led_off( LedPortType LedPort )
  21. {
  22.         if( LED_RED == LedPort )        //LED_RED
  23.         {
  24.                 RED_LED_SetHigh();                //红色LED引脚置高,红色LED灭
  25.         }
  26.         else                                                //LED_BLUE
  27.         {
  28.                 ;        //绿色LED引脚置高,蓝色LED灭
  29.         }
  30.         
  31. }

  32. /**
  33.   * @brief :LED闪烁
  34.   * @param :
  35.   *                        @LedPort:LED选择,红色或绿色
  36.   * @note  :无
  37.   * @retval:无
  38.   */
  39. void drv_led_flashing( LedPortType LedPort )
  40. {
  41.         //引脚翻转,LED闪烁
  42.         if( LED_RED == LedPort )
  43.         {
  44.                 RED_LED_Toggle();        
  45.         }
  46.         else
  47.         {
  48.                 ;
  49.         }
  50. }
按钮的使用,也是非常容易,直接使用MCC生成的函数
  1. /**
  2.   * @brief :按键查询
  3.   * @param :无
  4.   * @note  :无
  5.   * @retval:
  6.   *                        0:按键没有按下
  7.   *                        1:检测到按键动作
  8.   */
  9. uint8_t drv_button_check( void )
  10. {
  11.         if( 0x00 == (BUTTON_GetValue() & 0x01 ))                //检测按键输入状态
  12.         {
  13.                 drv_delay_ms( 40 );                        //消抖
  14.                 if( 0x00 == (BUTTON_GetValue()& 0x01 ))
  15.                 {
  16.                         return 1;                                //按键按下,返回按键状态
  17.                 }
  18.         }
  19.         
  20.         return 0;
  21. }
cc1101库函数里的相关操作也是使用MCC的生成函数替换
  1. #define CC1101_SET_CSN_HIGH( )                        spi_set_nss_high( )
  2. #define CC1101_SET_CSN_LOW( )                        spi_set_nss_low( )

  3. #define CC1101_GET_GDO0_STATUS( )                (( GDO0_GetValue()) == 0x00 ) ? 0 : 1        //GDO0状态
  4. #define CC1101_GET_GDO2_STATUS( )                (( GDO2_GetValue()) == 0x00 ) ? 0 : 1        //GDO2状态



至此,我们基本上没去了解关于寄存器的任何知识,就完成了移植。

最后奉上main.c的完整内容

  1. #include "mcc_generated_files/mcc.h"
  2. #include"drv_periph/inc/drv_CC1101.h"
  3. #include"drv_mcu/inc/drv_button.h"
  4. #include"drv_mcu/inc/drv_delay.h"
  5. #include"drv_mcu/inc/drv_spi.h"
  6. #include"drv_mcu/inc/drv_uart.h"
  7. #include"drv_mcu/inc/drv_led.h"
  8. #include"string.h"

  9. #define        __CC1101_TX_TEST__        
  10. /*
  11.                          Main application
  12. */
  13. const char *g_Text = "Hello I'm PIC18F16Q41";
  14. uint8_t g_TxMode = 0, g_UartRxFlag = 0;
  15. uint8_t g_UartRxBuffer[ 100 ] = { 0 };
  16. uint8_t g_RF24L01RxBuffer[ 32 ] = { 0 };
  17. /** 发送模式定义 */
  18. enum
  19. {
  20.         TX_MODE_1 = 0,                //发送模式1,发送固定的字符串
  21.         TX_MODE_2                        //发送模式2,发送串口接收到的数据
  22. };

  23. void main(void)
  24. {
  25.     uint8_t i = 0;
  26.     // Initialize the device
  27.     SYSTEM_Initialize();

  28.     // If using interrupts in PIC18 High/Low Priority Mode you need to enable the Global High and Low Interrupts
  29.     // If using interrupts in PIC Mid-Range Compatibility Mode you need to enable the Global Interrupts
  30.     // Use the following macros to:

  31.     // Enable the Global Interrupts
  32.     //INTERRUPT_GlobalInterruptEnable();

  33.     // Disable the Global Interrupts
  34.     //INTERRUPT_GlobalInterruptDisable();
  35.     printf("Hello\n");
  36.             //CC1101初始化
  37.         CC1101_Init( );
  38.         for( i = 0; i < 6; i++ )
  39.         {
  40.                 led_red_flashing( );
  41.                 led_green_flashing( );
  42.                 drv_delay_ms( 500 );
  43.         }
  44.    
  45. #ifdef        __CC1101_TX_TEST__        
  46.         
  47.         //按键初始化
  48.         drv_button_init( );

  49.         while( 1 )        
  50.         {
  51.                 //模式切换
  52.                 //Demo程序默认为发送模式1,即发送固定字符串“Hello I'm PIC18F16Q41"”,可以通过按键切换到发送模式2,即通过串口发送数据,按键的作用就是切换发送模式1 2
  53.                 //如果在程序移植过程中不需要两种发送模式,删除下面 if 语句程序块和按键初始化程序即可
  54.                 if( BUTOTN_PRESS_DOWN == drv_button_check( ))
  55.                 {
  56.                         g_TxMode = 1 - g_TxMode;                //模式会在 TX_MODE_1( 0 ),TX_MODE_2( 1 )之间切换
  57.                         
  58.                         //状态显示清零
  59.                         led_green_off( );
  60.                         led_red_off( );
  61.                         
  62.                         if( TX_MODE_1 == g_TxMode )
  63.                         {
  64.                                 for( i = 0; i < 6; i++ )               
  65.                                 {
  66.                                         led_red_flashing( );        //固定发送模式,红灯闪烁3次
  67.                                         drv_delay_ms( 500 );               
  68.                                 }
  69.                         }
  70.                         else
  71.                         {
  72.                                 for( i = 0; i < 2; i++ )
  73.                                 {
  74.                                         led_red_flashing( );        //串口发送模式,绿灯闪烁3次
  75.                                         drv_delay_ms( 500 );
  76.                                 }
  77.                         }
  78.                 }

  79.                 //如果在程序移植过程中不需要两种发送模式,删除上面 if 语句程序块和按键初始化程序即可
  80.                 //模式切换

  81.                
  82.                 //发送
  83.                 if( TX_MODE_1 == g_TxMode )
  84.                 {
  85.                         CC1101_Tx_Packet( (uint8_t *)g_Text, strlen(g_Text) , ADDRESS_CHECK );                //模式1发送固定字符,1S一包
  86.                         drv_delay_ms( 1000 );        
  87.                         led_red_flashing( );                        
  88.                 }
  89.                 else
  90.                 {        
  91.                         //查询串口数据
  92.                         i = drv_uart_rx_bytes( g_UartRxBuffer );
  93.                         
  94.                         if( 0 != i )
  95.                         {
  96.                                 CC1101_Tx_Packet( g_UartRxBuffer, i , ADDRESS_CHECK );
  97.                                 led_red_flashing( );
  98.                         }
  99.                 }
  100.         }   
  101. #else
  102. /*
  103. 接收
  104. */
  105.     while (1)
  106.     {
  107. //        DELAY_milliseconds(1000);
  108. //        printf("Hello World \n");

  109.         CC1101_Clear_RxBuffer( );
  110.                 CC1101_Set_Mode( RX_MODE );

  111.                 i = CC1101_Rx_Packet( g_RF24L01RxBuffer );                //接收字节
  112.                 if( 0 != i )
  113.                 {
  114.                         led_red_flashing( );
  115.                         drv_uart_tx_bytes( g_RF24L01RxBuffer, i );        //输出接收到的字节
  116.             printf("\n");
  117.                 }
  118.     }
  119. #endif   
  120. }
  121. /**
  122. End of File
  123. */



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

打赏榜单

21小跑堂 打赏了 10.00 元 2021-11-26
理由:恭喜通过原创文章审核!请多多加油哦!

 楼主| gaoyang9992006 发表于 2021-11-19 21:47 | 显示全部楼层
最后请注意我设置上拉电阻使能的两个输入管脚,如果你的单片机不支持内部上拉电阻,需要外置一个,不然嘿嘿,你就找不到问题出哪儿了,就是收发不成功。。。
lcczg 发表于 2021-11-24 16:15 | 显示全部楼层
内部的上拉电阻还是很有用的
 楼主| gaoyang9992006 发表于 2021-11-24 18:21 | 显示全部楼层
lcczg 发表于 2021-11-24 16:15
内部的上拉电阻还是很有用的

是的,并非所有的单片机都具备内部上拉,不然关键时候真的会掉链子。
740071911 发表于 2021-11-26 13:15 | 显示全部楼层
传一个视频看看呢
 楼主| gaoyang9992006 发表于 2021-11-26 13:47 | 显示全部楼层
740071911 发表于 2021-11-26 13:15
传一个视频看看呢

出差去了,在徐州,突发疫情,被困在这了,估计要一个月才能回去。视频是看测试通信距离的视频,还是看软件编写过程的视频
493326732 发表于 2021-11-27 12:44 | 显示全部楼层
666啊  
493326732 发表于 2021-11-27 15:19 | 显示全部楼层
有相关的视频教程吗   
zydl123 发表于 2021-11-27 19:43 | 显示全部楼层
测试过吗?最远距离是多少
cjseng 发表于 2021-11-28 12:19 | 显示全部楼层
zydl123 发表于 2021-11-27 19:43
测试过吗?最远距离是多少

天线匹配良好的话,100米还是有的
 楼主| gaoyang9992006 发表于 2021-11-28 12:25 | 显示全部楼层
cjseng 发表于 2021-11-28 12:19
天线匹配良好的话,100米还是有的

我跑了一条街,400米外测试,信号完好,收发正常。更远没去测。

评论

你用的波特率是多少?  发表于 2021-11-28 17:31
wangchangwenqq 发表于 2021-11-28 15:26 | 显示全部楼层
准备弄一个通过蓝牙收发,
梅花香自123 发表于 2021-11-28 23:40 | 显示全部楼层
很详细的开发资料6666
740071911 发表于 2021-11-29 08:46 | 显示全部楼层
gaoyang9992006 发表于 2021-11-26 13:47
出差去了,在徐州,突发疫情,被困在这了,估计要一个月才能回去。视频是看测试通信距离的视频,还是看软 ...

是遥控小车跑起来的视频,软件编写视频那要很长世间吧
pzsh 发表于 2021-11-29 13:55 | 显示全部楼层
gaoyang9992006 发表于 2021-11-28 12:25
我跑了一条街,400米外测试,信号完好,收发正常。更远没去测。

这么远的距离
 楼主| gaoyang9992006 发表于 2021-11-29 22:38 | 显示全部楼层

无障碍应该可以直接800米到1000米。
 楼主| gaoyang9992006 发表于 2021-11-30 11:25 | 显示全部楼层
740071911 发表于 2021-11-29 08:46
是遥控小车跑起来的视频,软件编写视频那要很长世间吧

关注我的抖音,抖音发了视频,抖音号:
123237318
怀揣少年梦 发表于 2021-12-3 13:59 | 显示全部楼层
距离这么远啊,请问用了多大增益的天线?
hi0712 发表于 2021-12-3 14:26 | 显示全部楼层
复杂了复杂了
kyzhd 发表于 2021-12-3 14:41 | 显示全部楼层
gaoyang9992006 发表于 2021-11-26 13:47
出差去了,在徐州,突发疫情,被困在这了,估计要一个月才能回去。视频是看测试通信距离的视频,还是看软 ...

我大徐州也有疫情了,楼主注意安全啊。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:如果你觉得我的分享或者答复还可以,请给我点赞,谢谢。

2052

主题

16403

帖子

222

粉丝
快速回复 在线客服 返回列表 返回顶部