发新帖本帖赏金 10.00元(功能说明)我要提问
12下一页
返回列表
打印
[PIC®/AVR®/dsPIC®产品]

为了遥控的更远,我用PIC18F16Q41驱动CC1101收发数据

[复制链接]
3651|26
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 gaoyang9992006 于 2021-11-19 21:42 编辑

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

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

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

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

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

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


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


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


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

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

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

/**
  * @brief :LED灭
  * @param :
  *                        @LedPort:LED选择,红色或绿色
  * @note  :无
  * @retval:无
  */
void drv_led_off( LedPortType LedPort )
{
        if( LED_RED == LedPort )        //LED_RED
        {
                RED_LED_SetHigh();                //红色LED引脚置高,红色LED灭
        }
        else                                                //LED_BLUE
        {
                ;        //绿色LED引脚置高,蓝色LED灭
        }
        
}

/**
  * @brief :LED闪烁
  * @param :
  *                        @LedPort:LED选择,红色或绿色
  * @note  :无
  * @retval:无
  */
void drv_led_flashing( LedPortType LedPort )
{
        //引脚翻转,LED闪烁
        if( LED_RED == LedPort )
        {
                RED_LED_Toggle();        
        }
        else
        {
                ;
        }
}
按钮的使用,也是非常容易,直接使用MCC生成的函数
/**
  * @brief :按键查询
  * @param :无
  * @note  :无
  * @retval:
  *                        0:按键没有按下
  *                        1:检测到按键动作
  */
uint8_t drv_button_check( void )
{
        if( 0x00 == (BUTTON_GetValue() & 0x01 ))                //检测按键输入状态
        {
                drv_delay_ms( 40 );                        //消抖
                if( 0x00 == (BUTTON_GetValue()& 0x01 ))
                {
                        return 1;                                //按键按下,返回按键状态
                }
        }
        
        return 0;
}
cc1101库函数里的相关操作也是使用MCC的生成函数替换
#define CC1101_SET_CSN_HIGH( )                        spi_set_nss_high( )
#define CC1101_SET_CSN_LOW( )                        spi_set_nss_low( )

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



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

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

#include "mcc_generated_files/mcc.h"
#include"drv_periph/inc/drv_CC1101.h"
#include"drv_mcu/inc/drv_button.h"
#include"drv_mcu/inc/drv_delay.h"
#include"drv_mcu/inc/drv_spi.h"
#include"drv_mcu/inc/drv_uart.h"
#include"drv_mcu/inc/drv_led.h"
#include"string.h"

#define        __CC1101_TX_TEST__        
/*
                         Main application
*/
const char *g_Text = "Hello I'm PIC18F16Q41";
uint8_t g_TxMode = 0, g_UartRxFlag = 0;
uint8_t g_UartRxBuffer[ 100 ] = { 0 };
uint8_t g_RF24L01RxBuffer[ 32 ] = { 0 };
/** 发送模式定义 */
enum
{
        TX_MODE_1 = 0,                //发送模式1,发送固定的字符串
        TX_MODE_2                        //发送模式2,发送串口接收到的数据
};

void main(void)
{
    uint8_t i = 0;
    // Initialize the device
    SYSTEM_Initialize();

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

    // Enable the Global Interrupts
    //INTERRUPT_GlobalInterruptEnable();

    // Disable the Global Interrupts
    //INTERRUPT_GlobalInterruptDisable();
    printf("Hello\n");
            //CC1101初始化
        CC1101_Init( );
        for( i = 0; i < 6; i++ )
        {
                led_red_flashing( );
                led_green_flashing( );
                drv_delay_ms( 500 );
        }
   
#ifdef        __CC1101_TX_TEST__        
        
        //按键初始化
        drv_button_init( );

        while( 1 )        
        {
                //模式切换
                //Demo程序默认为发送模式1,即发送固定字符串“Hello I'm PIC18F16Q41"”,可以通过按键切换到发送模式2,即通过串口发送数据,按键的作用就是切换发送模式1 2
                //如果在程序移植过程中不需要两种发送模式,删除下面 if 语句程序块和按键初始化程序即可
                if( BUTOTN_PRESS_DOWN == drv_button_check( ))
                {
                        g_TxMode = 1 - g_TxMode;                //模式会在 TX_MODE_1( 0 ),TX_MODE_2( 1 )之间切换
                        
                        //状态显示清零
                        led_green_off( );
                        led_red_off( );
                        
                        if( TX_MODE_1 == g_TxMode )
                        {
                                for( i = 0; i < 6; i++ )               
                                {
                                        led_red_flashing( );        //固定发送模式,红灯闪烁3次
                                        drv_delay_ms( 500 );               
                                }
                        }
                        else
                        {
                                for( i = 0; i < 2; i++ )
                                {
                                        led_red_flashing( );        //串口发送模式,绿灯闪烁3次
                                        drv_delay_ms( 500 );
                                }
                        }
                }

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

               
                //发送
                if( TX_MODE_1 == g_TxMode )
                {
                        CC1101_Tx_Packet( (uint8_t *)g_Text, strlen(g_Text) , ADDRESS_CHECK );                //模式1发送固定字符,1S一包
                        drv_delay_ms( 1000 );        
                        led_red_flashing( );                        
                }
                else
                {        
                        //查询串口数据
                        i = drv_uart_rx_bytes( g_UartRxBuffer );
                        
                        if( 0 != i )
                        {
                                CC1101_Tx_Packet( g_UartRxBuffer, i , ADDRESS_CHECK );
                                led_red_flashing( );
                        }
                }
        }   
#else
/*
接收
*/
    while (1)
    {
//        DELAY_milliseconds(1000);
//        printf("Hello World \n");

        CC1101_Clear_RxBuffer( );
                CC1101_Set_Mode( RX_MODE );

                i = CC1101_Rx_Packet( g_RF24L01RxBuffer );                //接收字节
                if( 0 != i )
                {
                        led_red_flashing( );
                        drv_uart_tx_bytes( g_RF24L01RxBuffer, i );        //输出接收到的字节
            printf("\n");
                }
    }
#endif   
}
/**
End of File
*/



480336197a748393e8.png (50.12 KB )

480336197a748393e8.png

使用特权

评论回复

打赏榜单

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
内部的上拉电阻还是很有用的

是的,并非所有的单片机都具备内部上拉,不然关键时候真的会掉链子。

使用特权

评论回复
5
740071911| | 2021-11-26 13:15 | 只看该作者
传一个视频看看呢

使用特权

评论回复
6
gaoyang9992006|  楼主 | 2021-11-26 13:47 | 只看该作者
740071911 发表于 2021-11-26 13:15
传一个视频看看呢

出差去了,在徐州,突发疫情,被困在这了,估计要一个月才能回去。视频是看测试通信距离的视频,还是看软件编写过程的视频

使用特权

评论回复
7
493326732| | 2021-11-27 12:44 | 只看该作者
666啊  

使用特权

评论回复
8
493326732| | 2021-11-27 15:19 | 只看该作者
有相关的视频教程吗   

使用特权

评论回复
9
zydl123| | 2021-11-27 19:43 | 只看该作者
测试过吗?最远距离是多少

使用特权

评论回复
10
cjseng| | 2021-11-28 12:19 | 只看该作者
zydl123 发表于 2021-11-27 19:43
测试过吗?最远距离是多少

天线匹配良好的话,100米还是有的

使用特权

评论回复
11
gaoyang9992006|  楼主 | 2021-11-28 12:25 | 只看该作者
cjseng 发表于 2021-11-28 12:19
天线匹配良好的话,100米还是有的

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

使用特权

评论回复
评论
cjseng 2021-11-28 17:31 回复TA
你用的波特率是多少? 
12
wangchangwenqq| | 2021-11-28 15:26 | 只看该作者
准备弄一个通过蓝牙收发,

使用特权

评论回复
13
梅花香自123| | 2021-11-28 23:40 | 只看该作者
很详细的开发资料6666

使用特权

评论回复
14
740071911| | 2021-11-29 08:46 | 只看该作者
gaoyang9992006 发表于 2021-11-26 13:47
出差去了,在徐州,突发疫情,被困在这了,估计要一个月才能回去。视频是看测试通信距离的视频,还是看软 ...

是遥控小车跑起来的视频,软件编写视频那要很长世间吧

使用特权

评论回复
15
pzsh| | 2021-11-29 13:55 | 只看该作者
gaoyang9992006 发表于 2021-11-28 12:25
我跑了一条街,400米外测试,信号完好,收发正常。更远没去测。

这么远的距离

使用特权

评论回复
16
gaoyang9992006|  楼主 | 2021-11-29 22:38 | 只看该作者

无障碍应该可以直接800米到1000米。

使用特权

评论回复
17
gaoyang9992006|  楼主 | 2021-11-30 11:25 | 只看该作者
740071911 发表于 2021-11-29 08:46
是遥控小车跑起来的视频,软件编写视频那要很长世间吧

关注我的抖音,抖音发了视频,抖音号:
123237318

使用特权

评论回复
18
怀揣少年梦| | 2021-12-3 13:59 | 只看该作者
距离这么远啊,请问用了多大增益的天线?

使用特权

评论回复
19
hi0712| | 2021-12-3 14:26 | 只看该作者
复杂了复杂了

使用特权

评论回复
20
kyzhd| | 2021-12-3 14:41 | 只看该作者
gaoyang9992006 发表于 2021-11-26 13:47
出差去了,在徐州,突发疫情,被困在这了,估计要一个月才能回去。视频是看测试通信距离的视频,还是看软 ...

我大徐州也有疫情了,楼主注意安全啊。

使用特权

评论回复
发新帖 本帖赏金 10.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:西安公路研究院南京院
简介:主要工作从事监控网络与通信网络设计,以及从事基于嵌入式的通信与控制设备研发。擅长单片机嵌入式系统物联网设备开发,音频功放电路开发。

1898

主题

15639

帖子

199

粉丝