|
main.c
/****************************************************************************/
/* */
/* Copyright (c) 2016, 老馬工作室 */
/* All rights reserved. */
/* */
/* Email:pcwebmaster@163.com */
/****************************************************************************/
/****************************************************************************/
/* 文 件 名:comint.c */
/* 版 本:Version 1.0 */
/* 描 述:串行口中斷帶通訊協(xié)議測(cè)試 */
/* 主控芯片:NuMicro M0516*/
/* 晶振頻率:11.0592MHz */
/* 作 者:pcwebmaster(北極狼) */
/* 函 數(shù): */
/* system_init */
/* com_send_command */
/* com_command_receive*/
/*CalCRC16_1021*/
/*command_decoder*/
/*send_command*/
/* 測(cè) 試: 發(fā)送:16 16 02 01 02 01 00 35 03 94 BD接收:49 AA 15 */
/* 測(cè)試現(xiàn)象: */
/* 歷史記錄:20016.02.18測(cè)試通過(guò) */
/* 北極狼 20016-02-18 Creat Inital version. (Version 1.0) */
/****************************************************************************/
#include <stdio.h>
#include "M051Series.h"
#include "comint.h"
#define PLL_CLOCK 50000000
/*---------------------------------------------------------------------------------------------------------*/
/* Global variables */
/*---------------------------------------------------------------------------------------------------------*/
void SYS_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock */
/*---------------------------------------------------------------------------------------------------------*/
/* Enable Internal RC 22.1184MHz clock */
CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);
/* Waiting for Internal RC clock ready */
CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);
/* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));
/* Enable external XTAL 12MHz clock */
CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);
/* Waiting for external XTAL clock ready */
CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);
/* Set core clock as PLL_CLOCK from PLL */
CLK_SetCoreClock(PLL_CLOCK);
/* Enable UART module clock */
CLK_EnableModuleClock(UART0_MODULE);
/* Select UART module clock source */
// CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_CLKDIV_UART(1));CLK_CLKSEL1_UART_S_HIRC
CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HIRC, CLK_CLKDIV_UART(1));
/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function */
/*---------------------------------------------------------------------------------------------------------*/
/* Set P3 multi-function pins for UART0 RXD and TXD */
SYS->P3_MFP &= ~(SYS_MFP_P30_Msk | SYS_MFP_P31_Msk);
SYS->P3_MFP |= (SYS_MFP_P30_RXD0 | SYS_MFP_P31_TXD0);
}
void UART0_Init()
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init UART */
/*---------------------------------------------------------------------------------------------------------*/
/* Reset IP */
SYS_ResetModule(UART0_RST);
/* Configure UART0 and set UART0 Baudrate */
UART_Open(UART0, 115200);
//UART_Open(UART0, 9600);
/* Enable Interrupt and install the call back function */
UART_ENABLE_INT(UART0, (UART_IER_RDA_IEN_Msk));// | UART_IER_THRE_IEN_Msk | UART_IER_RTO_IEN_Msk));
NVIC_EnableIRQ(UART0_IRQn);
// while(g_bWait);
}
void Uart0Send(int32_t Bytes)
{
UART0->THR = Bytes;
while ((UART0->FSR&TX_EMPTY) != 0x00); //檢查發(fā)送FIFO是否為空
}
/*---------------------------------------------------------------------------------------------------------*/
/* MAIN function */
/*---------------------------------------------------------------------------------------------------------*/
int main(void)
{
//int8_t i,j;
SYS_UnlockReg();/* Unlock protected registers */
SYS_Init();/* Init System, IP clock and multi-function I/O */
SYS_LockReg();/* Lock protected registers */
UART0_Init();/* Init UART0 for printf and testing */
buff_init();
/*---------------------------------------------------------------------------------------------------------*/
/* SAMPLE CODE */
/*---------------------------------------------------------------------------------------------------------*/
printf("\n\nCPU @ %dHz\n", SystemCoreClock);
printf("\r\n 世界,你好!\r\n");
printf("\r\n USART0測(cè)試正常! \r\n");
while(1)
{
com_command_receive();
}
}
COMINT.C
/****************************************************************************/
/* */
/* Copyright (c) 2016, 老馬工作室 */
/* All rights reserved. */
/* */
/* Email:pcwebmaster@163.com */
/****************************************************************************/
/****************************************************************************/
/* 文 件 名:comint.c */
/* 版 本:Version 1.0 */
/* 描 述:串行口中斷帶通訊協(xié)議測(cè)試 */
/* 主控芯片:NuMicro M0516*/
/* 晶振頻率:11.0592MHz */
/* 作 者:pcwebmaster(北極狼) */
/* 函 數(shù): */
/* system_init */
/* com_send_command */
/* com_command_receive*/
/*CalCRC16_1021*/
/*command_decoder*/
/*send_command*/
/* 測(cè) 試: 發(fā)送:16 16 02 01 02 01 00 35 03 94 BD接收:49 AA 15 */
/* 測(cè)試現(xiàn)象: */
/* 歷史記錄:20016.02.18測(cè)試通過(guò) */
/* 北極狼 20016-02-18 Creat Inital version. (Version 1.0) */
/****************************************************************************/
#include "comint.h"
uint8_t pint_buf[MAX_RINTL]; /* 串口接收緩沖區(qū) */
uint8_t pint_read; /* 串口緩沖區(qū)讀指針 */
uint8_t pint_write; /* 串口緩沖區(qū)寫(xiě)指針 */
uint8_t psend_int; /* 串口發(fā)送允許標(biāo)志 */
uint8_t serial_flag = 0; /* 串口接收數(shù)據(jù)標(biāo)志位 */
uint8_t prec_buf[MAX_COMMAND_LEN];/* 命令接收緩沖區(qū) */
uint8_t prec_num; /* 命令接收緩沖區(qū)字節(jié)數(shù) */
uint8_t serial_lengthl = 0; /* 消息命令長(zhǎng)度低8位 */
uint16_t serial_length = 0; /* 消息命令長(zhǎng)度16位 */
uint8_t ADDRESS[2]={ZU,ZHAN}; /* byte0:通訊組地址, byte1:開(kāi)發(fā)板地址 */
/* 串口發(fā)送一個(gè)字節(jié) */
void com_send_command(uint16_t Data)
{
UART0->THR = Data;
while ((UART0->FSR&TX_EMPTY) != 0x00); //檢查發(fā)送FIFO是否為空
}
/* 串口接收數(shù)據(jù)處理 */
void com_command_receive(void)
{
uint8_t var1,var4;
uint16_t crc_data = 0;
var4 = pint_read;
if (var4 != pint_write)
{
var1 = pint_buf[var4];
var4 = var4+1;
if (var4 >= MAX_RINTL)
var4=0;
pint_read = var4;
switch(serial_flag)
{
case 0: /*收到起始位*/
if (var1 == SYN)
{
serial_flag = 1;
//com_send_command(0x01); //測(cè)試
}
else
{
serial_flag = 0;
}
break;
case 1:/*收到起始位*/
if (var1 == SYN)
{
serial_flag = 2;
//com_send_command(0x02); //測(cè)試
}
else
{
serial_flag = 0;
}
break;
case 2:/*收到同步位*/
if (var1 == STX)
{
serial_flag = 3;
//com_send_command(0x03);//測(cè)試
}
else
{
serial_flag = 0;
}
break;
case 3: /*收到組地址*/
if (var1 == ADDRESS[0])
{
serial_flag = 4;
prec_num = 1;
prec_buf[0] = var1;
//com_send_command(0x04); //測(cè)試
}
else
{
serial_flag = 0;
}
break;
case 4:/*收到本機(jī)地址或者廣播地址*/
if ( (var1 == ADDRESS[1]) || (var1 == 0) )
{
prec_num = 2;
prec_buf[1] = var1;
serial_flag = 5;
//com_send_command(0x05); //測(cè)試
}
else
{
serial_flag = 0;
}
break;
case 5:/*數(shù)據(jù)長(zhǎng)度*/
prec_num = 3;
prec_buf[2] = var1;
serial_lengthl = var1;
serial_flag = 6;
//com_send_command(0x06);//測(cè)試
break;
case 6:
prec_num = 4;
prec_buf[3] = var1;
serial_length |= var1;
serial_length = ( (serial_length << 8) & 0xff00 ) + serial_lengthl + 3;
serial_flag = 7;
//com_send_command(0x07);//測(cè)試
break;
case 7:
prec_buf[prec_num] = var1;
prec_num++;
serial_length--;
if (serial_length == 0)
{
crc_data = CalCRC16_1021(prec_buf, prec_num - 2); /* 計(jì)算crc校驗(yàn)和(從組地址開(kāi)始到ETX )*/
if ( ( (crc_data & 0x00ff) == prec_buf[prec_num - 2]) && ( ( (crc_data >>8) & 0x00ff) == prec_buf[prec_num - 1]) ) /* 校驗(yàn)和正確 */
{
prec_num = 1;
var1 = 0;
if ( (prec_buf[4] >= 0x31) && (prec_buf[4] <= 0x3b) ) /* 命令有效 */
{
if (prec_buf[1] != 0x00) /* 如果不是廣播地址則回應(yīng)ACK*/
com_send_command(0x49);//測(cè)試 msg_last_push(MSG_ACK,0);
//send_command(ACK); //測(cè)試
command_decoder(); /* 如果校驗(yàn)和正確,則進(jìn)行命令解碼 */
}
else
{
send_command(NAK); //測(cè)試
}
}
else
{
send_command(NAK); //測(cè)試
}
serial_flag = 0;
prec_num = 1;
}
break;
default:
serial_flag = 0;
prec_num = 1;
break;
}
}
}
/* 命令解碼子程序 */
void command_decoder(void)
{
// uint8_t i = 0;
if (prec_buf[4] == 0x31) /* 設(shè)置報(bào)警閾值 */
{
com_send_command(0x11);//測(cè)試
return;
}
else if (prec_buf[4] == 0x32) /* 請(qǐng)求報(bào)警閾值 */
{
com_send_command(0x12);//測(cè)試?
return;
}
else if (prec_buf[4] == 0x33) /* 修改當(dāng)前時(shí)間 */
{
com_send_command(0x13);//測(cè)試
return;
}
else if (prec_buf[4] == 0x34) /* 請(qǐng)求當(dāng)前時(shí)間 */
{
com_send_command(0x14);//測(cè)試
return;
}
else if (prec_buf[4] == 0x35) /* 請(qǐng)求當(dāng)前數(shù)據(jù) */
{
com_send_command(0xAA);//測(cè)試
//__nop();
com_send_command(0x15);//測(cè)試
return;
}
else if (prec_buf[4] == 0x36) /* 請(qǐng)求看門(mén)狗信息*/
{
com_send_command(0x16);//測(cè)試
return;
}
else if (prec_buf[4] == 0x37) /* 請(qǐng)求報(bào)警情況 */
{
com_send_command(0x17);//測(cè)試
return;
}
else if (prec_buf[4] == 0x38) /* 配置設(shè)備地址 */
{
ADDRESS[0] = prec_buf[5]; /* 通訊組地址 */
ADDRESS[1] = prec_buf[6]; /* 開(kāi)發(fā)板地址 */
com_send_command(0x181);//測(cè)試
return;
}
else if (prec_buf[4] == 0x39) /* 請(qǐng)求設(shè)備地址 */
{
com_send_command(0x19);//測(cè)試
return;
}
else if (prec_buf[4] == 0x3a) /* 控制模擬量輸出 */
{
com_send_command(0x1A);//測(cè)試?
return;
}
else if (prec_buf[4] == 0x3b) /* 控制開(kāi)關(guān)量輸出 */
{
com_send_command(0x1B);//測(cè)試
return;
}
//if (prec_buf[4] == 0x00) /* 如果是廣播地址 */
// {
//com_send_command(SYN);
//com_send_command(0x00);
//com_send_command(SYN);
// return;
// }
}
/* 向PC主機(jī)發(fā)送消息幀,入口參數(shù):消息類(lèi)型 */
void send_command(uint8_t command)
{
switch (command)
{
case ACK:
com_send_command(SYN);
com_send_command(SYN);
com_send_command(ACK);
break;
case NAK:
com_send_command(SYN);
com_send_command(SYN);
com_send_command(NAK);
break;
default:
break;
}
}
void buff_init(void)
{
uint8_t loop;
loop = UART0->RBR; /* 清串口緩沖區(qū) */
for (loop=0; loop<MAX_RINTL; loop++)
{
pint_buf[loop] = 0;
}
}
/*計(jì)算CRC校驗(yàn)和使用MTT(0X1021)
參數(shù):
pBuff 為需計(jì)算CRC的緩沖區(qū)的頭指針
BufferLen 緩沖區(qū)長(zhǎng)度(以字節(jié)計(jì))
*/
u_short CalCRC16_1021(uint8_t x[], u_short BufferLen)
{
u_short i;
uint8_t j;
u_short crc16 = 0;
u_short mask = 0x1021;
uint8_t *pByteBuffer;
uint8_t tmpbyte;
u_short calval;
pByteBuffer = &x[0];
for (i = 0; i < BufferLen; i++)
{
tmpbyte = *pByteBuffer;
calval = tmpbyte << 8;
for (j = 0; j < 8; j++)
{
if ((crc16 ^ calval) & 0x8000)
crc16 = (crc16 << 1) ^ mask;
else
crc16 <<= 1;
calval <<= 1;
}
pByteBuffer++;
}
return crc16;
}
/*---------------------------------------------------------------------------------------------------------*/
/* ISR to handle UART Channel 0 interrupt event */
/*---------------------------------------------------------------------------------------------------------*/
void UART0_IRQHandler(void)
{
uint8_t temp;
uint8_t temp1;
if(UART0->ISR & RDA_INT) //檢查是否接收數(shù)據(jù)中斷
{
while(UART0->ISR & RDA_IF) //獲取所有接收到的數(shù)據(jù)
{
while (UART0->FSR & RX_EMPTY); //檢查接收FIFO是否為空
temp1 = UART0->RBR; //讀取數(shù)據(jù)
temp = pint_write + 1; /* 判斷是否可以寫(xiě)入 */
if (temp == MAX_RINTL)
{
temp=0;
}
if (temp != pint_read)
{
pint_buf[pint_write] = temp1; /* 讀取數(shù)據(jù) */
pint_write = temp;
}
}
}
}
COMINT.h
#ifndef __COMINT_H__
#define __COMINT_H__
#include <stdio.h>
#include "M051Series.h"
#define RXBUFSIZE 8//1024
#define TX_EMPTY(1<<22)
#define RX_EMPTY(1<<14)
#define RDA_INT(1<<8)
#define RDA_IF(1<<0)
typedefunsigned shortu_short;
#define ZU0x01 /*組地址*///通訊地址修改這兩項(xiàng)
#define ZHAN0x02 /*站地址*///通訊地址修改這兩項(xiàng)
#define MAX_RINTL 16 /* 串口接收緩沖區(qū)長(zhǎng)度 */
#define SYN 0x16 /* 通訊同步位*/
#define STX 0x02 /* 通訊起始位*/
#define ETX 0x03 /* 通訊結(jié)束位*/
#define ACK 0x06
#define NAK 0x15
#define MSG_ACK 2 /* 正確應(yīng)答信息 */
#define MSG_NAK 3 /* 錯(cuò)誤應(yīng)答信息 */
#define MAX_COMMAND_LEN 16 /* 串口接受命令長(zhǎng)度 */
extern char str_test[25] ;
extern uint8_t pint_read; // 串口緩沖區(qū)讀指針 */
extern uint8_t pint_write; // 串口緩沖區(qū)寫(xiě)指針
//extern uint8_t data psend_int; // 串口發(fā)送允許標(biāo)志
extern uint8_t pint_buf[MAX_RINTL]; // 串口接收緩沖區(qū)
extern uint8_t serial_flag; /* 串口接收數(shù)據(jù)標(biāo)志位 */
extern uint8_t prec_buf[MAX_COMMAND_LEN];/* 命令接收緩沖區(qū) */
/* 串口發(fā)送一個(gè)字節(jié) */
extern void com_send_command(uint16_t Data);
/* 串口接收數(shù)據(jù)處理 */
extern void com_command_receive(void);
/* 串口接收初始化 */
extern void buff_init(void);
///* 串口接收一字節(jié)數(shù)據(jù) */
//unsigned char UartReadChar(void); //reentrant
/*計(jì)算CRC校驗(yàn)和使用MTT(0X1021)
參數(shù):
pBuff 為需計(jì)算CRC的緩沖區(qū)的頭指針
BufferLen 緩沖區(qū)長(zhǎng)度(以字節(jié)計(jì))
*/
u_short CalCRC16_1021(uint8_t x[], u_short BufferLen);
/* 命令解碼子程序 */
void command_decoder(void);
/* 向主機(jī)發(fā)送消息幀,入口參數(shù):消息類(lèi)型 */
void send_command(uint8_t command);
#endif
|
|