#include "SWM221.h"


/* 测试条件：SWM221 <==CAN_RX/TX==> CAN 收发器（如 TJA1050）<==CAN_H/L==> CAN 分析仪
 * 错误处理演示：
 *	1、将 CAN 收发器与 CAN 分析仪断开，触发 ACK 错误，CAN->TXERR 从 0 递增到 128，然后保持不变
 *	2、将 SWM221 与 CAN 收发器断开，触发位错误，CAN->TXERR 继续递增到 255，触发 Bus Off，CAN->CR.RST 自动置 1，CAN 模块处于复位状态
 *	3、ISR 中在检测到 Bus Off 后执行 CAN_Open(CAN0) 使 CAN 模块退出复位状态，此时将上面断开的连接恢复，CAN->TXERR 将逐渐递减到0，CAN 模块恢复正常工作
*/


void SerialInit(void);

int main(void)
{
	CAN_InitStructure CAN_initStruct;
	
	SystemInit();
	
	SerialInit();
	
	PORT_Init(PORTC, PIN2, PORTC_PIN2_CAN0_RX, 1);
	PORT_Init(PORTC, PIN3, PORTC_PIN3_CAN0_TX, 0);
	
	CAN_initStruct.Mode = CAN_MODE_NORMAL;
	CAN_initStruct.CAN_bs1 = CAN_BS1_5tq;
	CAN_initStruct.CAN_bs2 = CAN_BS2_4tq;
	CAN_initStruct.CAN_sjw = CAN_SJW_2tq;
	CAN_initStruct.Baudrate = 50000;
	CAN_initStruct.RXNotEmptyIEn = 1;
	CAN_initStruct.ArbitrLostIEn = 0;
	CAN_initStruct.ErrPassiveIEn = 1;
	CAN_Init(CAN0, &CAN_initStruct);
	
	CAN_INTEn(CAN0, CAN_IT_ERR_WARN | CAN_IT_RX_OVERFLOW);
	
	CAN_SetFilter32b(CAN0, CAN_FILTER_1, 0x00122122, 0x1FFFFFFE);		//接收ID为0x00122122、0x00122123的扩展包
	CAN_SetFilter16b(CAN0, CAN_FILTER_2, 0x122, 0x7FE, 0x101, 0x7FF);	//接收ID为0x122、123、0x101的标准包
	
	CAN_Open(CAN0);
	
	while(1)
	{
		uint8_t tx_data[8] = {1, 2, 3, 4, 5, 6, 7, 8};
		
		CAN_Transmit(CAN0, CAN_FRAME_STD, 0x133, tx_data, 8, 1);
		while(CAN_TXComplete(CAN0) == 0) __NOP();
		
		printf("\r\nCAN->TXERR: %d\r\n", CAN0->TXERR);
		
		for(int i = 0; i < SystemCoreClock / 16; i++) __NOP();
	}
}


void CAN0_Handler(void)
{
	uint32_t can_if = CAN_INTStat(CAN0);
	
	if(can_if & CAN_IF_RXDA_Msk)
	{
		CAN_RXMessage msg;
		
		CAN_Receive(CAN0, &msg);
		
		if(msg.size > 0)
		{
			printf("\r\nReceive %s: %08X, ", msg.format == CAN_FRAME_STD ? "STD" : "EXT", msg.id);
			for(int i = 0; i < msg.size; i++) printf("%02X, ", msg.data[i]);
			printf("\r\n");
		}
		else if(msg.remote == 1)	//远程帧
		{
			printf("\r\nReceive %s Remote Request\r\n", msg.format == CAN_FRAME_STD ? "STD" : "EXT");
		}
	}
	
	if(can_if & CAN_IF_RXOV_Msk)
	{
		printf("\r\nCAN RX Overflow\r\n");
		
		CAN_Close(CAN0);
		for(int i = 0; i < CyclesPerUs; i++) __NOP();
		CAN_Open(CAN0);
	}
	
	if(can_if & CAN_IF_ERRWARN_Msk)
	{
		if(CAN0->SR & CAN_SR_BUSOFF_Msk)
		{
			printf("\r\nCAN Bus Off\r\n");
			printf("\r\nCAN->CR.RST = %d\r\n", CAN0->CR & CAN_CR_RST_Msk ? 1 : 0);
			
			CAN_Open(CAN0);			//Bus Off recovery
		}
		else if(CAN0->SR & CAN_SR_ERRWARN_Msk)
		{
			printf("\r\nCAN Error Warning\r\n");
		}
	}
	
	if(can_if & CAN_IF_ERRPASS_Msk)
	{
		printf("\r\nCAN Error Passive\r\n");
	}
}


void SerialInit(void)
{
	UART_InitStructure UART_initStruct;
	
	PORT_Init(PORTA, PIN0, PORTA_PIN0_UART0_RX, 1);	//GPIOA.0配置为UART0 RXD
	PORT_Init(PORTA, PIN1, PORTA_PIN1_UART0_TX, 0);	//GPIOA.1配置为UART0 TXD
 	
 	UART_initStruct.Baudrate = 57600;
	UART_initStruct.DataBits = UART_DATA_8BIT;
	UART_initStruct.Parity = UART_PARITY_NONE;
	UART_initStruct.StopBits = UART_STOP_1BIT;
	UART_initStruct.RXThreshold = 3;
	UART_initStruct.RXThresholdIEn = 0;
	UART_initStruct.TXThreshold = 3;
	UART_initStruct.TXThresholdIEn = 0;
	UART_initStruct.TimeoutTime = 10;
	UART_initStruct.TimeoutIEn = 0;
 	UART_Init(UART0, &UART_initStruct);
	UART_Open(UART0);
}

/****************************************************************************************************************************************** 
* 函数名称: fputc()
* 功能说明: printf()使用此函数完成实际的串口打印动作
* 输    入: int ch		要打印的字符
*			FILE *f		文件句柄
* 输    出: 无
* 注意事项: 无
******************************************************************************************************************************************/
int fputc(int ch, FILE *f)
{
	UART_WriteByte(UART0, ch);
	
	while(UART_IsTXBusy(UART0));
 	
	return ch;
}
