本帖最后由 yangyurong 于 2024-12-28 18:22 编辑
使用CAN总线实现主从板RGB灯互相控制拿到开发板,还没有进行过点灯操作,但是不想随便点灯,那种普通的亮灯灭灯没啥技术含量,也不好玩,本着将CAN总线技术
融入到RGB点呼吸灯操作,这样可以通过两个CAN 节点之间互相控制对方,实现各种绚丽的呼吸灯技术,模拟汽车车灯的控制。
好了,开始进入主题。
上面是我用到的硬件平台,一个主板,一个从板,通过2根杜邦线连接双方的CAN接口。
实验现象大家可以查看我的哔哩哔哩空间
https://www.bilibili.com/video/BV1pPCaYkEZW/?spm_id_from=333.1387.homepage.video_card.click
1板的key1可以将2板的LED灯改为红色,key2可以将2板的LED灯改为蓝色。
2板的key1可以将1板的LED灯改为黄色,key2可以将1板的LED灯改为绿色。
这就是CAN的特性,互为主从,互相切换。
核心代码如下:
#include "user_config.h"
#include "board.h"
#include <string.h>
#include <stdio.h>
static __IO uint32_t g_timingDelay;
unsigned char pwm_time=0;
unsigned char pwm_r_data=0;
unsigned char pwm_g_data=0;
unsigned char pwm_b_data=0;
unsigned char led_mode = 0;
static __IO uint32_t g_ms_delay;
void SysTick_Init(void)
{
/* Update System Core Clock info */
SystemCoreClockUpdate();
/* SystemFrequency / 1000 = 1ms */
if (SysTick_Config(SystemCoreClock / 100000))
{
/* Capture error */
while (1);
}
}
void SysTick_Delay_ms(__IO uint32_t nTime)
{
g_timingDelay = nTime;
while(g_timingDelay != 0);
}
void TimingDelay_Decrement(void)
{
if(g_timingDelay != 0)
{
g_timingDelay--;
}
pwm_time++;
g_ms_delay++;
if(pwm_time>=255)
{
pwm_time=0;
}
if(pwm_time<=pwm_r_data)
{
LED_On(LED_RED);
}
else
{
LED_Off(LED_RED);
}
if(pwm_time<=pwm_g_data)
{
LED_On(LED_GREEN);
}
else
{
LED_Off(LED_GREEN);
}
if(pwm_time<=pwm_b_data)
{
LED_On(LED_BLUE);
}
else
{
LED_Off(LED_BLUE);
}
if(g_ms_delay >= 500)
{
g_ms_delay = 0;
}
}
uint8_t can_send_msg(uint32_t id, uint8_t *msg, uint8_t len);
void LED_PWM(unsigned char a,unsigned char b,unsigned char c) //三路PWM,R/G/B
{
pwm_r_data=a;
pwm_g_data=b;
pwm_b_data=c;
}
void breath_fresh_Red(void);
void breath_fresh_Green(void);
void breath_fresh_Blue(void);
void breath_fresh_Yellow(void);
void breath_fresh_Pink(void);
void breath_fresh_Teal(void);
void breath_fresh_White(void);
void breath_fresh_BreathingWithCorlorChanging(void);
void ChasingEffect_Red(void);
void ChasingEffect_Wait(void);
void Call_Effect(void);
void Drop_effect_Red(void);
void ledPulse(uint8_t r, uint8_t g, uint8_t b, uint8_t min_brightness,
uint8_t max_brightness, uint16_t delay_step);
void RGB_LED_CONTROL(uint8_t mode);
/** @addtogroup G32A1465_Examples
@{
*/
/** @addtogroup CAN_ClassicFrames
@{
*/
/** @defgroup CAN_ClassicFrames_Macros Macros
@{
*/
/* CAN instance */
#define CAN0_INSTANCE (0U)
/* MB0 is used to receive standard CAN frames */
#define RX_MB_0 (0U)
/* MB1 is used to receive extended CAN frames */
#define RX_MB_1 (1U)
/* The MB used to transmit CAN frames */
#define TX_MB (2U)
/* CAN message IDs */
#define RX_CAN_MESSAGE_ID (0x111U)
#define RX_CAN_MESSAGE_ID1 (0x111U)
#define TX_CAN_MESSAGE_ID_2 (0x222U)
CAN_MSG_BUF_T rxFrame0;
CAN_MSG_BUF_T rxFrame1;
/**@} end of group CAN_ClassicFrames_Macros*/
/** @defgroup CAN_ClassicFrames_Variables Variables
@{
*/
/* Indicate MB0 receive is completed */
volatile uint8_t g_mb0ReceiveCompleted = 0;
/* Indicate MB1 receive is completed */
volatile uint8_t g_mb1ReceiveCompleted = 0;
volatile uint8_t payload1[64];
volatile uint8_t CAN_DAT;
/**@} end of group CAN_ClassicFrames_Variables*/
/** @defgroup CAN_ClassicFrames_Functions Functions
@{
*/
/*!
* @brief This function is called when a CAN event occurred
*/
void CanEventCallback(
uint8_t instance,
CAN_EVENT_TYPE_T eventType,
uint32_t mbIndex,
CAN_STATE_T *driverState)
{
CAN_DATA_INFO_T rxDataInfo;
uint8_t i;
/* A frame was received in the configured Rx MB */
if (eventType == CAN_EVENT_RX_COMPLETE)
{
/* Set the receive complete flags */
if (mbIndex == RX_MB_0)
{
// memcpy(payload1, rxFrame0.data, rxFrame0.dataLen);
if(rxFrame0.messageId == RX_CAN_MESSAGE_ID1)
{
if((rxFrame0.data[0]==0x30)&&(rxFrame0.data[1]==1))
{
g_mb0ReceiveCompleted = 1;
}
else if((rxFrame0.data[0]==0x30)&&(rxFrame0.data[1]==2))
{
g_mb0ReceiveCompleted = 2;
}
else if((rxFrame0.data[0]==0x30)&&(rxFrame0.data[1]==3))
{
g_mb0ReceiveCompleted = 3;
}
else if((rxFrame0.data[0]==0x30)&&(rxFrame0.data[1]==4))
{
g_mb0ReceiveCompleted = 4;
}
else if((rxFrame0.data[0]==0x30)&&(rxFrame0.data[1]==5))
{
g_mb0ReceiveCompleted = 5;
}
else if((rxFrame0.data[0]==0x30)&&(rxFrame0.data[1]==6))
{
g_mb0ReceiveCompleted = 6;
}
else if((rxFrame0.data[0]==0x30)&&(rxFrame0.data[1]==7))
{
g_mb0ReceiveCompleted = 7;
}
else if((rxFrame0.data[0]==0x30)&&(rxFrame0.data[1]==8))
{
g_mb0ReceiveCompleted = 8;
}
}
rxDataInfo.msgIdType = CAN_ID_STANDARD;
rxDataInfo.dataLen = rxFrame0.dataLen;
rxDataInfo.fdEnable = false;
rxDataInfo.isRemote = false;
CAN_ReceiveNonBlocking(CAN0_INSTANCE, RX_MB_0, &rxFrame0);
}
if (mbIndex == RX_MB_1)
{
if(rxFrame1.messageId == RX_CAN_MESSAGE_ID1)
{
memcpy(payload1, rxFrame1.data, rxFrame1.dataLen);
g_mb1ReceiveCompleted = true;
}
rxDataInfo.msgIdType = CAN_ID_STANDARD;
rxDataInfo.dataLen = rxFrame1.dataLen;
rxDataInfo.fdEnable = false;
rxDataInfo.isRemote = false;
CAN_ReceiveNonBlocking(CAN0_INSTANCE, RX_MB_1, &rxFrame1);
}
}
}
/*!
* @brief This function is called when the KEY1 button is pressed
*/
void Key1Handler(void)
{
/* Send standard CAN frame */
uint8_t payload[8] = {0x30, 2, 0, 0, 0, 0, 0, 0};
can_send_msg(TX_CAN_MESSAGE_ID_2, payload, 8);
}
/*!
* @brief This function is called when the KEY2 button is pressed
*/
void Key2Handler(void)
{
/* Send extended CAN frame */
uint8_t payload[8] = {0x30, 3, 0, 0, 0, 0, 0, 0};
can_send_msg(TX_CAN_MESSAGE_ID_2, payload, 8);
}
/*!
* @brief Main function
* @param None
* @retval Exit code
*/
int main(void)
{
bool exit = false;
CAN_STATE_T canState;
CAN_TIME_SEGMENT_T canBitrate;
/* Initialize clock */
CLOCK_SYS_Init(&g_clockConfig);
/* Initialize pins */
PINS_Init(NUM_OF_CONFIGURED_PINS0, g_pinsConfig);
/* Initialize LEDs */
LED_Init();
LED_On(LED_GREEN);
LED_On(LED_RED);
// LED_On(LED_BLUE);
SysTick_Init();
/* Initialize buttons */
BTN_Init();
BTN_InstallKey1Handler(Key1Handler);
BTN_InstallKey2Handler(Key2Handler);
/* Initialize the CAN controller, bitrate is 250K */
CAN_Init(CAN0_INSTANCE, &canState, &g_canConfig);
/* Get the current CAN bitrate */
CAN_GetBitrate(CAN0_INSTANCE, &canBitrate);
/* Configure Tx MB */
CAN_DATA_INFO_T txMbInfo = {
.msgIdType = CAN_ID_STANDARD, /* Standard CAN ID */
.dataLen = 8, /* Used only to initialize the MB, will be updated when send data */
.fdEnable = false, /* Disable CAN FD */
.isRemote = false
};
CAN_ConfigureTxMb(CAN0_INSTANCE, TX_MB, &txMbInfo, 0);
/* Use individual Rx masking for the MBs */
CAN_SetRxMaskType(CAN0_INSTANCE, CAN_RX_MASK_INDIVIDUAL);
/* Configure Rx MB0, it will receive standard frames with ID 1 */
CAN_DATA_INFO_T rxMb0Info = {
.msgIdType = CAN_ID_STANDARD, /* Standard CAN ID */
.dataLen = 8, /* Max data length for classic CAN is 8 bytes */
.fdEnable = false, /* Disable CAN FD */
.isRemote = false
};
CAN_ConfigureRxMb(CAN0_INSTANCE, RX_MB_0, &rxMb0Info, RX_CAN_MESSAGE_ID);
CAN_SetRxIndividualMask(CAN0_INSTANCE, CAN_ID_STANDARD, RX_MB_0, 0xFFFFFFFF);
/* Configure Rx MB1, it will receive extended frames with ID 1 */
CAN_DATA_INFO_T rxMb1Info = {
.msgIdType = CAN_ID_EXTENDED, /* Extended CAN ID */
.dataLen = 8, /* Max data length for classic CAN is 8 bytes */
.fdEnable = false, /* Disable CAN FD */
.isRemote = false
};
CAN_ConfigureRxMb(CAN0_INSTANCE, RX_MB_1, &rxMb1Info, 0x112);
CAN_SetRxIndividualMask(CAN0_INSTANCE, CAN_ID_EXTENDED, RX_MB_1, 0xFFFFFFFF);
/* Set the CAN event callback handler */
CAN_InstallEventCallback(CAN0_INSTANCE, &CanEventCallback, NULL);
CAN_ReceiveNonBlocking(CAN0_INSTANCE, RX_MB_0, &rxFrame0);
CAN_ReceiveNonBlocking(CAN0_INSTANCE, RX_MB_1, &rxFrame1);
LED_PWM(0,0,0);
while (1)
{
// ledPulse(0,0,0,0,255,500);
// Drop_effect_Red();
// Call_Effect();
// ChasingEffect_Wait();
// ChasingEffect_Red();
// breath_fresh_BreathingWithCorlorChanging();
// LED_On(LED_RED);
// delay_ms(200);
// LED_Off(LED_RED);
// delay_ms(200);
// breath_fresh_Red();
// breath_fresh_Green();
// breath_fresh_Blue();
// breath_fresh_Yellow();
// breath_fresh_Pink();
// breath_fresh_Teal();
// breath_fresh_White();
// RGB_LED_CONTROL(led_mode);
switch (g_mb0ReceiveCompleted)
{
case 1:
breath_fresh_Red();
break;
case 2:
breath_fresh_Green();
break;
case 3:
breath_fresh_Blue();
break;
case 4:
breath_fresh_Yellow();
break;
case 5:
breath_fresh_Pink();
break;
case 6:
breath_fresh_Teal();
break;
case 7:
breath_fresh_White();
break;
case 8:
breath_fresh_BreathingWithCorlorChanging();
break;
}
}
return 0;
}
/**
* @brief CAN ·¢ˍһשʽ¾ݍ
* @NOTE ·¢ˍ¸ |
|