一起来玩 thread +多路继电器控制目前继电器还是用LED代替显示,这样不至于那么恐怖,因为我用的是交流继电器。
介绍一下:
从pin_mux.c和原理图对照了解FRDM_KW41Z板子配置的IO口,看 哪些没用到,哪些用到哪里了。
PTC4 是 button SW3
PTC5 是 button SW4
PTA18, LED RGB_B
PTA19, LED RGB_G
PTB0, PTB0 LED3
PTC1 LED RGB_R
PTC18 PTC1
PTC16,PTC17,PTC18,PTC19 SPI总线 AT45DB041E芯片
PTC6,PTC7 UART0
PTB0,PTB1,PTC1,PTC2,PTC3 I2C
PTB17,连 到时钟了,暂时不管 它。
PTA16(J2-4),PTA17(J2-5)好像是没用哦。
PTB18,PTB2,PTB3,J4-2,J4-3 ,J4-4没用 那就用这三个IO控制继电器吧!!!
pin_mux.c中:
PIN_MUX.C中加入初始化时钟和GPIO函数
//---------------------------------------------------------------------------------------------------------
//PTB18,PTB2,PTB3,J4-2,J4-3 ,J4-4没用
#define PIN2_IDX 2u /*!< Pin number for pin 0 in a port */
#define PIN3_IDX 3u /*!< Pin number for pin 1 in a port */
#define PIN18_IDX 18u /*!< Pin number for pin 18 in a port */
/*
// 注意:这里IO口方向还没定哦,特别注意啊!!!:
void BOARD_InitRELAYs(void) {
CLOCK_EnableClock(kCLOCK_PortB); /* Port B Clock GateControl: Clock enabled */
PORT_SetPinMux(PORTB, PIN2_IDX, kPORT_MuxAsGpio); /* PORTB2 is configured as out */
PORT_SetPinMux(PORTB, PIN3_IDX, kPORT_MuxAsGpio); /* PORTB3 is configured as out*/
PORT_SetPinMux(PORTB, PIN18_IDX, kPORT_MuxAsGpio); /* PORTB18 is configured as out */
}
2,在头文件PIN_MUX.h 中加入该函数
void BOARD_InitRELAYs(void);
3,LED.c中加入
void RELAY_Init(void)
{
BOARD_InitRELAYs();//这里初始化时钟,把IO变为GPIO
(void)GpioOutputPinInit(relayPins, 3);//这里吧继电器设置为输出
}
//RELAY_t 1,2,3 RELAY_MOde_t mode on/off 1,0
static void RELAY_Set
(
const gpioOutputPinConfig_t * pOutputConfig,
RELAY_OpMode_t operation
)
{
if(operation ==off)
GpioSetPinOutput(pOutputConfig);;
if(operation ==on)
GpioClearPinOutput(pOutputConfig);
}
// RELAY_Operate(RELAY1,on);
// RELAY_Operate(RELAY2,off);
void RELAY_Operate
(
RELAY_t relay,
RELAY_OpMode_t operation
)
{
if(relay==RELAY1)
RELAY_Set( relayPins,operation);
if(relay==RELAY2)
RELAY_Set( relayPins,operation);
if(relay==RELAY3)
RELAY_Set( relayPins,operation);
}
4,Led.h中加入
#define RELAY1 0x1;
#define RELAY2 0x2;
#define RELAY3 0x4;
typedef uint8_t RELAY_t;
typedef enum RELAY_OpMode_tag{
on,
off
}RELAY_OpMode_t;
extern void RELAY_Init(void);
extern void RELAY_Operate(RELAY_t led, RELAY_OpMode_t operation);
5,gpio_pins.c中加入
//-------------------------------------------------
gpioOutputPinConfig_t relayPins[] = {
{
.gpioPort = gpioPort_B_c,
.gpioPin = 2,
.outputLogic = 1,
.slewRate = pinSlewRate_Slow_c,
.driveStrength = pinDriveStrength_Low_c
},
{
.gpioPort = gpioPort_B_c,
.gpioPin = 3,
.outputLogic = 1,
.slewRate = pinSlewRate_Slow_c,
.driveStrength = pinDriveStrength_Low_c
},
{
.gpioPort = gpioPort_B_c,
.gpioPin = 18,
.outputLogic = 1,
.slewRate = pinSlewRate_Slow_c,
.driveStrength = pinDriveStrength_Low_c
},
};
6,Gpio_pins.h中加入
extern gpioOutputPinConfig_t relayPins[];
//----------------------------------------------------------------
7,app_init.c中void main_task(uint32_t param) ==》BOARD_InitLEDs()后面加入函数
RELAY_Init();
下面理清一下coap的发送和接受,看到哪里加入继电器的操作函数
从shell_ip_c中可以看出,发送coap CON POST 2001::1 /led on 这样的命令传送 coap消息。
#define APP_LED_URI_PATH "/led"
#define APP_TEMP_URI_PATH "/temp"
#define APP_SINK_URI_PATH "/sink"
这几个控制LED,温度等的路径在router_eligible_device_app.c中
/*==================================================================================================
Private functions
==================================================================================================*/
/*!*************************************************************************************************
\private
\fn static void APP_InitCoapDemo(void)
\brief Initialize CoAP demo.
***************************************************************************************************/
static void APP_InitCoapDemo
(
void
)
{
coapRegCbParams_t cbParams[] = {{APP_CoapLedCb, (coapUriPath_t*)&gAPP_LED_URI_PATH},
{APP_CoapTempCb, (coapUriPath_t *)&gAPP_TEMP_URI_PATH},
#if LARGE_NETWORK
{APP_CoapResetToFactoryDefaultsCb, (coapUriPath_t*)&gAPP_RESET_URI_PATH},
#endif
{APP_CoapSinkCb, (coapUriPath_t *)&gAPP_SINK_URI_PATH}};
/*Register Services in COAP */
coapStartUnsecParams_t coapParams = {COAP_DEFAULT_PORT, AF_INET6};
mAppCoapInstId = COAP_CreateInstance(NULL, &coapParams, gIpIfSlp0_c,(coapRegCbParams_t *)cbParams,
NumberOfElements(cbParams));
}
这里吧这个LED的路径和处理函数APP_CoapLedCb,联系起来了。其他的像温度也是一样。其实我们完全可以在这里另辟蹊径整一个新路径和新的回调函数王道上面,
这样就可以不用\led 不如用\relay。后续再整吧。
/*!*************************************************************************************************
\private
\fn static void APP_CoapLedCb(sessionStatus sessionStatus, void *pData,
coapSession_t *pSession, uint32_tdataLen)
\brief This function is the callback function for CoAP LED message.
\brief It performs the required operations and sends back a CoAP ACK message.
\param [in] sessionStatus Status for CoAP session
\param [in] pData Pointer to CoAP message payload
\param [in] pSession Pointer to CoAP session
\param [in] dataLen Length of CoAP payload
***************************************************************************************************/
static void APP_CoapLedCb
(
coapSessionStatus_t sessionStatus,
void*pData,
coapSession_t *pSession,
uint32_t dataLen
)
{
/*Process the command only if it is a POST method */
if((pData) && (sessionStatus == gCoapSuccess_c) &&(pSession->code == gCoapPOST_c))
{
APP_ProcessLedCmd(pData, dataLen);
}
/*Send the reply if the status is Success or Duplicate */
if((gCoapFailure_c != sessionStatus) && (gCoapConfirmable_c ==pSession->msgType))
{
/* Send CoAP ACK */
COAP_Send(pSession, gCoapMsgTypeAckSuccessChanged_c, NULL, 0);
}
}
也就是说上面就是CO AP传送命令控制另一台LED的响应函数。那我们在这里放个RELAY的控制估计就能动起来,不过。
继续void APP_CoapLedCb函数,发现处理分两部分,一是处理LED,二是coap应答
if((pData) && (sessionStatus ==gCoapSuccess_c) && (pSession->code == gCoapPOST_c))
{
APP_ProcessLedCmd(pData, dataLen); //一是处理LED
}
/*Send the reply if the status is Success or Duplicate */
if((gCoapFailure_c != sessionStatus) && (gCoapConfirmable_c ==pSession->msgType))
{
/* Send CoAP ACK */
COAP_Send(pSession, gCoapMsgTypeAckSuccessChanged_c, NULL, 0);// 二是coap应答
}
static void APP_ProcessLedCmd
(
uint8_t *pCommand,
uint8_t dataLen
)
{
/*Set mode state */
APP_SetMode(mThrInstanceId, gDeviceMode_Application_c);
mFirstPushButtonPressed = FALSE;
/*Process command */
if(FLib_MemCmp(pCommand, "on",2))
{
App_UpdateStateLeds(gDeviceState_AppLedOn_c);
}
elseif(FLib_MemCmp(pCommand, "off",3))
{
App_UpdateStateLeds(gDeviceState_AppLedOff_c);
}
elseif(FLib_MemCmp(pCommand, "toggle",6))
{
App_UpdateStateLeds(gDeviceState_AppLedToggle_c);
}
elseif(FLib_MemCmp(pCommand, "flash",5))
{
App_UpdateStateLeds(gDeviceState_AppLedFlash_c);
}
elseif(FLib_MemCmp(pCommand, "rgb",3))
{
char* p = (char *)pCommand + strlen("rgb");
uint8_t redValue = 0, greenValue = 0, blueValue = 0;
appDeviceState_t appState = gDeviceState_AppLedRgb_c;
dataLen -= strlen("rgb");
此内容由EEWORLD论坛网友damiaa原创,如需转载或用于商业用途需征得作者同意并注明出处
while(dataLen != 0)
{
if(*p == 'r')
{
p++;
dataLen--;
redValue = NWKU_atoi(p);
}
if(*p == 'g')
{
p++;
dataLen--;
greenValue = NWKU_atoi(p);
}
if(*p == 'b')
{
p++;
dataLen--;
blueValue = NWKU_atoi(p);
}
dataLen--;
p++;
}
/* Update RGB values */
#if gLedRgbEnabled_d
Led_UpdateRgbState(redValue, greenValue, blueValue);
#else
appState = gDeviceState_AppLedOff_c;
if(redValue || greenValue || blueValue)
{
appState = gDeviceState_AppLedOn_c;
}
#endif
App_UpdateStateLeds(appState);
/* If device is leader and has received a RGB LED off command and therewere no previous button presses */
if((gpaThrAttr[mThrInstanceId]->devRole == gThrDevRole_Leader_c)&&
(!redValue && !greenValue && !blueValue) &&(leaderLedTimestamp == 0))
{
leaderLedTimestamp = (TMR_GetTimestamp()/1000000) +gAppRestoreLeaderLedTimeout_c;
}
}
elseif(FLib_MemCmp(pCommand, "color wheel",11))
{
#if gLedRgbEnabled_d
App_UpdateStateLeds(gDeviceState_AppLedColorWheel_c);
#else
App_UpdateStateLeds(gDeviceState_AppLedFlash_c);
#endif
}
}
APP_ProcessLedCmd具体分析了coap命令的内容和长度,分别出来,如”on” “off” “toggle” “flash” “rgb” "color wheel"
所以我们把继电器放 这里更好:
把前面 的控制继电器的语句放这里:
static void APP_ProcessLedCmd
(
。。。
//放最后面吧--------------------------------------------------------------------
if(FLib_MemCmp(pCommand, "rallon",6))
{
RELAY_Operate(RELAY1,on);
RELAY_Operate(RELAY2,on);
RELAY_Operate(RELAY3,on);
}
if(FLib_MemCmp(pCommand, "r1on",4))
{
RELAY_Operate(RELAY1,on);
}
if(FLib_MemCmp(pCommand, "r2on",4))
{
RELAY_Operate(RELAY2,on);
}
if(FLib_MemCmp(pCommand, "r3on",4))
{
RELAY_Operate(RELAY3,on);
}
if(FLib_MemCmp(pCommand, "rallon",6))
{
RELAY_Operate(RELAY1,on);
RELAY_Operate(RELAY2,on);
RELAY_Operate(RELAY3,on);
}
if(FLib_MemCmp(pCommand, "ralloff",7))
{
RELAY_Operate(RELAY1,off);
RELAY_Operate(RELAY2,off);
RELAY_Operate(RELAY3,off);
}
if(FLib_MemCmp(pCommand, "r1off",5))
{
RELAY_Operate(RELAY1,off);
}
if(FLib_MemCmp(pCommand, "r2off",5))
{
RELAY_Operate(RELAY2,off);
}
if(FLib_MemCmp(pCommand, "r3off",5))
{
RELAY_Operate(RELAY3,off);
}
//-------------------------------------------------------------------
}
这样程序的事就可以了。
下面用putty连接两个模块,一个模块下程序下去,另外一个控制它就可以了。具体如开始的图片。谢谢。
本帖最后由 damiaa 于 2017-7-31 09:30 编辑