| @@ -3,15 +3,20 @@ | |||
| /*定义信号量*/ | |||
| OS_EVENT* ModbusReceived; /*接收到modbus请求报文*/ | |||
| OS_EVENT* ModbusWriteFlash; /*接收到modbus写入Flash请求报文*/ | |||
| OS_EVENT* ModbusConnect; /*已接收到modbus正确报文*/ | |||
| /*定义任务栈*/ | |||
| static OS_STK AppTaskStartStk[APP_TASK_START_STK_SIZE]; | |||
| static OS_STK AppTaskModbusParseStk[APP_TASK_MODBUS_PARSE_STK_SIZE]; | |||
| static OS_STK AppTaskModbusWriteFlashStk[APP_TASK_MODBUS_WRITE_FLASH_STK_SIZE]; | |||
| static OS_STK AppTaskModbusConnectStk[APP_TASK_MODBUS_CONNECT_STK_SIZE]; | |||
| /*定义任务主体函数*/ | |||
| static void AppTaskStart (void *p_arg); | |||
| void AppTaskModbusParse (void *p_arg); | |||
| void AppTaskModbusWriteFlash(void *p_arg); | |||
| static void AppTaskModbusConnect(void *p_arg); | |||
| int main() | |||
| @@ -50,6 +55,13 @@ void AppTaskStart(void *p_arg) | |||
| /*创建信号量*/ | |||
| ModbusReceived = OSSemCreate(0); | |||
| ModbusWriteFlash = OSSemCreate(0); | |||
| ModbusConnect = OSSemCreate(0); | |||
| /*读取flash中的数据*/ | |||
| ModbusRegReadFlash(); | |||
| ModbusCoilReadFlash(); | |||
| /* 创建modbus协议帧解析任务 */ | |||
| OSTaskCreateExt(AppTaskModbusParse, | |||
| @@ -62,10 +74,53 @@ void AppTaskStart(void *p_arg) | |||
| (void *)0, | |||
| (INT16U )(OS_TASK_OPT_STK_CHK | |||
| | OS_TASK_OPT_STK_CLR)); | |||
| /* 创建modbus线圈写入flash任务 */ | |||
| OSTaskCreateExt(AppTaskModbusWriteFlash, | |||
| (void *)0, | |||
| (OS_STK *)&AppTaskModbusWriteFlashStk[APP_TASK_MODBUS_WRITE_FLASH_STK_SIZE - 1], | |||
| (INT8U )APP_TASK_MODBUS_WRITE_FLASH_PRIO, | |||
| (INT16U )APP_TASK_MODBUS_WRITE_FLASH_PRIO, | |||
| (OS_STK *)&AppTaskModbusWriteFlashStk[0], | |||
| (INT32U )APP_TASK_MODBUS_WRITE_FLASH_STK_SIZE, | |||
| (void *)0, | |||
| (INT16U )(OS_TASK_OPT_STK_CHK | |||
| | OS_TASK_OPT_STK_CLR)); | |||
| /* 创建modbus判断连接断开任务 */ | |||
| OSTaskCreateExt(AppTaskModbusConnect, | |||
| (void *)0, | |||
| (OS_STK *)&AppTaskModbusConnectStk[APP_TASK_MODBUS_CONNECT_STK_SIZE - 1], | |||
| (INT8U )APP_TASK_MODBUS_CONNECT_PRIO, | |||
| (INT16U )APP_TASK_MODBUS_CONNECT_PRIO, | |||
| (OS_STK *)&AppTaskModbusConnectStk[0], | |||
| (INT32U )APP_TASK_MODBUS_CONNECT_STK_SIZE, | |||
| (void *)0, | |||
| (INT16U )(OS_TASK_OPT_STK_CHK | |||
| | OS_TASK_OPT_STK_CLR)); | |||
| OSTaskDel(OS_PRIO_SELF); /* 删除启动任务自身 */ | |||
| OS_EXIT_CRITICAL(); /* 开中断 */ | |||
| } | |||
| static void AppTaskModbusConnect(void *p_arg) | |||
| { | |||
| OS_ERR err; | |||
| while(1) | |||
| { | |||
| OSSemPend(ModbusConnect, (3 * OS_TICKS_PER_SEC), &err); | |||
| /*正常接收*/ | |||
| if(err == OS_ERR_NONE) | |||
| { | |||
| /*灭灯*/ | |||
| GPIO_SetBits(GPIOF, GPIO_Pin_6); | |||
| } | |||
| /*超时未接收到,判断为连接断开*/ | |||
| else | |||
| { | |||
| /*点灯*/ | |||
| GPIO_ResetBits(GPIOF, GPIO_Pin_6); | |||
| } | |||
| } | |||
| } | |||
| @@ -10,7 +10,8 @@ | |||
| #include "app_cfg.h" | |||
| #include "sys_cfg.h" | |||
| #include "modbus.h" | |||
| #include "modbus_flash.h" | |||
| #include "string.h" | |||
| //void TimingDelay_Decrement(void); | |||
| @@ -19,6 +19,16 @@ void ModbusGpioInit(void) | |||
| /*复用初始化*/ | |||
| GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); | |||
| GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); | |||
| /*PF6用于点灯判断主站连接断开*/ | |||
| RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); | |||
| /*PF6配置为普通推挽输出*/ | |||
| GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; | |||
| GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; | |||
| GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; | |||
| GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; | |||
| GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; | |||
| GPIO_Init(GPIOF, &GPIO_InitStructure); | |||
| } | |||
| /*硬件有自动收发转换芯片,软件实现modbus只需要当成普通的全双工串口使用即可*/ | |||
| @@ -16,15 +16,15 @@ | |||
| <ShowSource>1</ShowSource> | |||
| </Trace1> | |||
| <StLinkDriver> | |||
| <stlinkserialNo>30303031</stlinkserialNo> | |||
| <stlinkfoundProbes /> | |||
| <stlinkResetStyle>0</stlinkResetStyle> | |||
| <stlinkResetStrategy>0</stlinkResetStrategy> | |||
| <CStepIntDis>_ 0</CStepIntDis> | |||
| <LeaveTargetRunning>_ 0</LeaveTargetRunning> | |||
| <stlinkResetStyle>0</stlinkResetStyle> | |||
| <stlinkResetStrategy>0</stlinkResetStrategy> | |||
| <stlinkserialNo>30303031</stlinkserialNo> | |||
| <stlinkfoundProbes /> | |||
| </StLinkDriver> | |||
| <DebugChecksum> | |||
| <Checksum>3816837042</Checksum> | |||
| <Checksum>171243166</Checksum> | |||
| </DebugChecksum> | |||
| <Exceptions> | |||
| <StopOnUncaught>_ 0</StopOnUncaught> | |||
| @@ -120,15 +120,21 @@ | |||
| <ShowTimeSum>1</ShowTimeSum> | |||
| <SumSortOrder>0</SumSortOrder> | |||
| </EventLog> | |||
| <TermIOLog> | |||
| <LoggingEnabled>_ 0</LoggingEnabled> | |||
| <LogFile>_ ""</LogFile> | |||
| </TermIOLog> | |||
| <DisassembleMode> | |||
| <mode>0</mode> | |||
| </DisassembleMode> | |||
| <Breakpoints2> | |||
| <Count>0</Count> | |||
| </Breakpoints2> | |||
| <LogFile> | |||
| <LoggingEnabled>_ 0</LoggingEnabled> | |||
| <LogFile>_ ""</LogFile> | |||
| <Category>_ 0</Category> | |||
| </LogFile> | |||
| <Aliases> | |||
| <Count>0</Count> | |||
| <SuppressDialog>0</SuppressDialog> | |||
| </Aliases> | |||
| <DriverProfiling> | |||
| <Enabled>0</Enabled> | |||
| <Mode>3</Mode> | |||
| @@ -142,14 +148,8 @@ | |||
| <CallStackStripe> | |||
| <ShowTiming>1</ShowTiming> | |||
| </CallStackStripe> | |||
| <DisassembleMode> | |||
| <mode>0</mode> | |||
| </DisassembleMode> | |||
| <Breakpoints2> | |||
| <Count>0</Count> | |||
| </Breakpoints2> | |||
| <Aliases> | |||
| <Count>0</Count> | |||
| <SuppressDialog>0</SuppressDialog> | |||
| </Aliases> | |||
| <TermIOLog> | |||
| <LoggingEnabled>_ 0</LoggingEnabled> | |||
| <LogFile>_ ""</LogFile> | |||
| </TermIOLog> | |||
| </settings> | |||
| @@ -4,6 +4,8 @@ | |||
| #include "string.h" | |||
| #include "modbus.h" | |||
| extern OS_EVENT* ModbusWriteFlash; /*接收到modbus写入coil请求报文*/ | |||
| extern OS_EVENT* ModbusConnect; /*已接收到modbus正确报文*/ | |||
| uint8_t ModbusErr; | |||
| /*0x270F + 1 = K10000 */ | |||
| @@ -35,6 +37,7 @@ uint8_t ModbusWriteCoil(uint16_t addres, uint8_t *data); | |||
| uint8_t ModbusExtReadOdd(uint16_t num); | |||
| /*USART接收空闲中断*/ | |||
| void USART1_IRQHandler(void) | |||
| { | |||
| @@ -102,6 +105,7 @@ void ModbusSend(uint8_t *txBuf, uint16_t len) | |||
| /*等待串口发送完成*/ | |||
| while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); | |||
| /*在此处等待3.5个字符的时间*/ | |||
| /*启动 DMA 发送*/ | |||
| DMA_Cmd(DMA2_Stream7, ENABLE); | |||
| } | |||
| @@ -140,6 +144,7 @@ void AppTaskModbusParse (void *p_arg) | |||
| ModbusErr = ERR_SLAVE_ADDRES; | |||
| continue; | |||
| } | |||
| OSSemPost(ModbusConnect); | |||
| frame.func = rxBuf[1]; | |||
| frame.opeAddres = ((uint16_t)rxBuf[2] << 8) | ((uint16_t)rxBuf[3]); | |||
| @@ -160,22 +165,38 @@ void AppTaskModbusParse (void *p_arg) | |||
| frame.wNum = rxBuf[6]; | |||
| memcpy(frame.wData, &rxBuf[7], frame.wNum); | |||
| ModbusErr = ModbusWriteCoils(frame.opeAddres, frame.opeNum, frame.wData); | |||
| if(ModbusErr == 0) | |||
| { | |||
| OSSemPost(ModbusWriteFlash); | |||
| } | |||
| break; | |||
| case 0x10:/*写多个寄存器*/ | |||
| frame.wNum = rxBuf[6]; | |||
| memcpy(frame.wData, &rxBuf[7], frame.wNum); | |||
| ModbusErr = ModbusWriteRegs(frame.opeAddres, frame.opeNum, frame.wData); | |||
| if(ModbusErr == 0) | |||
| { | |||
| OSSemPost(ModbusWriteFlash); | |||
| } | |||
| break; | |||
| case 0x05:/*写单个线圈*/ | |||
| memcpy(frame.wData, &rxBuf[4], 2); | |||
| ModbusErr = ModbusWriteCoil(frame.opeAddres, frame.wData); | |||
| if(ModbusErr == 0) | |||
| { | |||
| OSSemPost(ModbusWriteFlash); | |||
| } | |||
| break; | |||
| case 0x06:/*写单个寄存器*/ | |||
| memcpy(frame.wData, &rxBuf[4], 2); | |||
| ModbusErr = ModbusWriteReg(frame.opeAddres, frame.wData); | |||
| if(ModbusErr == 0) | |||
| { | |||
| OSSemPost(ModbusWriteFlash); | |||
| } | |||
| break; | |||
| default:/*功能码错误*/ | |||
| @@ -611,7 +632,6 @@ uint8_t ModbusExtReadOdd(uint16_t num) | |||
| AddCrc16(ModbusTxBuf, 3 + dataLen); | |||
| ModbusTxLen = 5 + dataLen; | |||
| } | |||
| OSTimeDlyHMSM(0, 0, 0, 10); | |||
| ModbusSend(ModbusTxBuf, ModbusTxLen); | |||
| } | |||
| return 0; | |||
| @@ -3,49 +3,66 @@ | |||
| #include "modbus.h" | |||
| #include "modbus_flash.h" | |||
| #include "string.h" | |||
| #include "os.h" | |||
| extern uint8_t ModbusCoil[1250]; | |||
| extern uint16_t ModbusReg[10000]; | |||
| extern uint8_t ModbusErr; | |||
| extern OS_EVENT* ModbusWriteFlash; /*接收到modbus写入coil请求报文*/ | |||
| uint8_t ModbusCoilWriteFlash(void) | |||
| uint8_t ModbusFlashWrite(void); | |||
| uint8_t ModbusErrReply(uint8_t func, uint8_t err); | |||
| void AppTaskModbusWriteFlash(void *p_arg) | |||
| { | |||
| OS_ERR err; | |||
| while(1) | |||
| { | |||
| OSSemPend(ModbusWriteFlash, 0, &err); | |||
| OSTimeDly(OS_TICKS_PER_SEC); | |||
| while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); | |||
| ModbusErr = ModbusFlashWrite(); | |||
| } | |||
| } | |||
| uint8_t ModbusFlashWrite(void) | |||
| { | |||
| uint32_t addres = MODBUS_FLASH_COIL_ADDR; | |||
| uint16_t halfWord; | |||
| FLASH_Status status; | |||
| FLASH_Unlock(); | |||
| FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | |||
| | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); | |||
| /*扇区擦除,写入之前必须先擦除*/ | |||
| status = FLASH_EraseSector(MODBUS_FLASH_SECTOR, VoltageRange_3); | |||
| if(status != FLASH_COMPLETE) | |||
| { | |||
| return ERR_SLAVE; | |||
| } | |||
| for(uint16_t i = 0; i < 1250; i += 2) | |||
| { | |||
| /*前面的放在低字节,后面的放在高字节*/ | |||
| halfWord = ((uint16_t)ModbusCoil[i + 1] << 8) | ((uint16_t)ModbusCoil[i]); | |||
| status = FLASH_ProgramHalfWord(addres, ModbusCoil[i]); | |||
| status = FLASH_ProgramHalfWord(addres, halfWord); | |||
| /*写入失败,停止写入*/ | |||
| if(status != FLASH_COMPLETE) | |||
| { | |||
| break; | |||
| return ERR_SLAVE; | |||
| } | |||
| addres += 2; | |||
| } | |||
| FLASH_Lock(); | |||
| } | |||
| uint8_t ModbusRegWriteFlash(void) | |||
| { | |||
| uint32_t addres = MODBUS_FLASH_REG_ADDR; | |||
| FLASH_Status status; | |||
| FLASH_Unlock(); | |||
| /*扇区擦除,写入之前必须先擦除*/ | |||
| status = FLASH_EraseSector(MODBUS_FLASH_SECTOR, VoltageRange_3); | |||
| addres = MODBUS_FLASH_REG_ADDR; | |||
| for(uint16_t i = 0; i < 10000; i++) | |||
| { | |||
| status = FLASH_ProgramHalfWord(addres, ModbusReg[i]); | |||
| @@ -53,23 +70,24 @@ uint8_t ModbusRegWriteFlash(void) | |||
| /*写入失败,停止写入*/ | |||
| if(status != FLASH_COMPLETE) | |||
| { | |||
| break; | |||
| return ERR_SLAVE; | |||
| } | |||
| addres += 2; | |||
| } | |||
| FLASH_Lock(); | |||
| return 0; | |||
| } | |||
| uint8_t ModbusRegReadFlash(void) | |||
| void ModbusRegReadFlash(void) | |||
| { | |||
| memcpy(ModbusCoil, (const void *)MODBUS_FLASH_COIL_ADDR, 1250); | |||
| memcpy(ModbusReg, (const void *)MODBUS_FLASH_REG_ADDR, sizeof(ModbusReg)); | |||
| } | |||
| uint8_t ModbusCoilReadFlash(void) | |||
| void ModbusCoilReadFlash(void) | |||
| { | |||
| memcpy(ModbusReg, (const void *)MODBUS_FLASH_REG_ADDR, 10000); | |||
| memcpy(ModbusCoil, (const void *)MODBUS_FLASH_COIL_ADDR, sizeof(ModbusCoil)); | |||
| } | |||
| @@ -5,14 +5,15 @@ | |||
| /*FLASH地址每+1,代表1字节*/ | |||
| /*Sector 11起始地址*/ | |||
| #define MODBUS_FLASH_BASE 0x080E0000UL | |||
| #define MODBUS_FLASH_BASE 0x080E0000UL | |||
| /*Sector 11编号*/ | |||
| #define MODBUS_FLASH_SECTOR FLASH_Sector_11 | |||
| #define MODBUS_FLASH_SECTOR FLASH_Sector_11 | |||
| /*线圈数据起始地址*/ | |||
| #define MODBUS_FLASH_COIL_ADDR MODBUS_FLASH_BASE | |||
| /*寄存器数据起始地址*/ | |||
| #define MODBUS_FLASH_REG_ADDR (MODBUS_FLASH_BASE + 0x4E2UL) /*0x4E2 = K1250*/ | |||
| void ModbusRegReadFlash(void); | |||
| void ModbusCoilReadFlash(void); | |||
| #endif | |||
| @@ -62,10 +62,10 @@ | |||
| //#define APP_CFG_TASK_EQ1_PRIO 7u | |||
| #define OS_TASK_TMR_PRIO (OS_LOWEST_PRIO - 2u) | |||
| #define APP_TASK_START_PRIO 10u | |||
| #define APP_TASK_MODBUS_PARSE_PRIO 3u | |||
| #define APP_TASK_START_PRIO 10u | |||
| #define APP_TASK_MODBUS_PARSE_PRIO 3u | |||
| #define APP_TASK_MODBUS_WRITE_FLASH_PRIO 9u | |||
| #define APP_TASK_MODBUS_CONNECT_PRIO 15u | |||
| /* | |||
| ********************************************************************************************************* | |||
| @@ -78,8 +78,10 @@ | |||
| #define APP_CFG_TASK_EQ_STK_SIZE 512u | |||
| #define APP_CFG_TASK_OBJ_STK_SIZE 256u | |||
| #define APP_TASK_START_STK_SIZE 256u | |||
| #define APP_TASK_MODBUS_PARSE_STK_SIZE 512u | |||
| #define APP_TASK_START_STK_SIZE 256u | |||
| #define APP_TASK_MODBUS_PARSE_STK_SIZE 512u | |||
| #define APP_TASK_MODBUS_WRITE_FLASH_STK_SIZE 512u | |||
| #define APP_TASK_MODBUS_CONNECT_STK_SIZE 256u | |||