本帖最后由 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
*/
|