Electricity/FWLIB/source/ENS1_UART.c

402 lines
12 KiB
C
Raw Permalink Normal View History

/*
*Copyright (C),2023 , NANOCHAP
*File name: ENS1_UART.C
*Author:
*Version: V1.0
*Date: 2023-11-
*Description:
*Function List:
History:
1.V1.0
Date:
Author:
Modification:
*/
/*
ENS1 uart特性说明
1 AMBA APB规范
2 115200bps波特率()
3 FIFO 16
4
5 ()
6 DMA
7
8
9 :
5678
11.52
*/
#include "my_header.h"
#include "ENS1_UART.h"
#include "ENS1_GPIO.h"
UART_FifoStructrue UART1_Fifo = {
.level = bytes_8 ,
.DMA_Enable =0 ,
.FIFO_Enable =1 ,
};
UART_InitStructure UART1_Init = {
.UART_BaudRate = 110000 , //计算出来的DLL DLH不为整数 1、需要校准RC精确度2、需要调整此处的波特率
.UART_HardwareFlowControl =0,
.FifoSetting = &UART1_Fifo ,
.stop_len = StopLen_1, //固定停止位1位
.Word_len = WordLen_8, //数据位8位
.Stick_EN = Stick_RESET, //禁用固定奇偶校验
.Even_EN = Even_SET, //奇偶校验选择
.Parity_EN = Parity_RESET, //禁用奇偶检验
};
UART_ITStructure UART1_ITSet = {
.UartIntModel = RLSI_EN | RDAI_EN ,
};
/*判断是否有中断挂起*/
uint8_t UART_INT_PEND(CMSDK_UART_TypeDef* UARTx) //为0时有UART的中断挂起
{
return (uint8_t)(UARTx->IIR & 0x1);
}
/*中断类型判断*/
uint8_t UART_INT_TYPE(CMSDK_UART_TypeDef* UARTx)
{
return (uint8_t)((UARTx->IIR >> 1) & 0x7 );
}
/*fifo 使用指示器*/
uint8_t UART_FIFO_USE(CMSDK_UART_TypeDef* UARTx) //0:非fifo模式 1fifo 使能
{
return (uint8_t)((UARTx->IIR >> 6) & 0x3);
}
/*清除传输FIFO*/
void UART_TXCLR(CMSDK_UART_TypeDef* UARTx)
{
UARTx->FCR |= (1<<2) ;
}
/*清除接收FIFO*/
void UART_RXCLR(CMSDK_UART_TypeDef* UARTx)
{
UARTx->FCR |= (1<<1);
}
/*FIFO使能*/
void UART_FIFOEnable(CMSDK_UART_TypeDef* UARTx)
{
UARTx->FCR |= (1);
}
/*FIFO关闭*/
void UART_FIFODisable(CMSDK_UART_TypeDef* UARTx)
{
UARTx->FCR &=~ 1;
}
/*接收数据*/
uint8_t READ_UART_RCVBuff(CMSDK_UART_TypeDef* UARTx )
{
return (uint8_t)(UARTx->RBR & 0xff);
}
/*发送数据*/
void WRITE_UART_THRBuff(CMSDK_UART_TypeDef* UARTx ,uint8_t data)
{
UARTx->THR = data;
}
/*FIFO 状态读取*/
uint8_t UART_RX_FIFO_LEN(CMSDK_UART_TypeDef* UARTx)
{
return (uint8_t)((UARTx->FSR & 0x001f0000)>>16); //读取当前接收FIFO数据长度
}
uint8_t UART_TX_FIFO_LEN(CMSDK_UART_TypeDef* UARTx)
{
return (uint8_t)((UARTx->FSR & 0x00001f00)>>8); //读取当前发送FIFO数据长度
}
uint8_t UART_RX_FIFO_FULL(CMSDK_UART_TypeDef* UARTx)
{
return (uint8_t)((((UARTx->FSR & 0x8)>> 3 )==1) ? (1) : (0)) ; //当前读取FIFO是否为满
}
uint8_t UART_RX_FIFO_EMPTY(CMSDK_UART_TypeDef* UARTx)
{
return (uint8_t)((((UARTx->FSR & 0x4) >> 2)==1) ? (1) : (0) ) ; //当前读取FIFO是否为空
}
uint8_t UART_TX_FIFO_FULL(CMSDK_UART_TypeDef* UARTx)
{
return (uint8_t)((((UARTx->FSR & 0x2) >> 1)==1) ? (1) : (0)) ; //当前发送FIFO是否为满
}
uint8_t UART_TX_FIFO_EMPTY(CMSDK_UART_TypeDef* UARTx)
{
return (uint8_t)(((UARTx->FSR & 0x1)==1) ? (1) : (0)) ; //当前发送FIFO是否为空
}
/*收发线状态获取*/
uint8_t UARTLine_RCVError(CMSDK_UART_TypeDef* UARTx)
{
return (uint8_t)((UARTx->LSR>>7) & 0x1); //返回0 没有错误, 返回1 在fifo和非fifo状态下都有一个校验/帧/或接收缓存或fifo 的中断指示默认不使能break
}
/*判断发送缓存是否为空*/
uint8_t UARTLine_TRANSEmpty(CMSDK_UART_TypeDef* UARTx)
{
return (uint8_t)((UARTx->LSR>>6) & 0x1) ;
}
/*判断THR是否为空*/
uint8_t UARTLine_THREmpty(CMSDK_UART_TypeDef* UARTx)
{
return (uint8_t)((UARTx->LSR>>5) & 0x1) ;
}
/*
UART需要以下步骤:
1.
2. (DLL和DLH)
3. 使FIFO(FCR)FIFO
FCR寄存器的 FIFOEN
4. (LCR)
5. (MCR)
uart都支持自动流量控制
6. FREE位
(PMU)TXRST和RXRST位来释放位并使能UART
*/
//uart初始化参数1uart0/1参数2uart参数设置结构体
void UART_Init(CMSDK_UART_TypeDef *CMSDK_UART, UART_InitStructure* uart_paraX){
uint16_t divisor_value;
uint8_t overSamp_mode;
/* 1 GPIO - alt_function*/
if(CMSDK_UART == CMSDK_UART0){
PCLK_Enable(UART0_PCLK_EN);
GPIO_AltFunction(UART0_RX , ALT_FUNC1); //rx
GPIO_AltFunction(UART0_TX , ALT_FUNC1); //tx
2025-09-30 14:07:39 +08:00
// 修复正确配置GPIO方向
// GPIO2 (RX) 应该是输入
CMSDK_GPIO->OE &= ~(1 << UART0_RX); // 禁用输出
CMSDK_GPIO->IE |= (1 << UART0_RX); // 使能输入
// GPIO3 (TX) 应该是输出
CMSDK_GPIO->IE &= ~(1 << UART0_TX); // 禁用输入
CMSDK_GPIO->OE |= (1 << UART0_TX); // 使能输出
}
else if(CMSDK_UART == CMSDK_UART1)
{
PCLK_Enable(UART1_PCLK_EN);
GPIO_AltFunction(UART1_RX , ALT_FUNC1); //RX
GPIO_AltFunction(UART1_TX , ALT_FUNC1); //TX
2025-09-30 14:07:39 +08:00
// 修复正确配置GPIO方向
// GPIO12 (RX) 应该是输入
CMSDK_GPIO->OE &= ~(1 << UART1_RX); // 禁用输出
CMSDK_GPIO->IE |= (1 << UART1_RX); // 使能输入
// GPIO13 (TX) 应该是输出
CMSDK_GPIO->IE &= ~(1 << UART1_TX); // 禁用输入
CMSDK_GPIO->OE |= (1 << UART1_TX); // 使能输出
// 确保TX引脚初始化为高电平
CMSDK_GPIO->DATAOUT |= (1 << UART1_TX);
}
/* 2 波特率设置*/
if(((CMSDK_UART->MDR)&0x00000001) == 0)
{
overSamp_mode = 16; //默认0
}
else
{
overSamp_mode = 13;
}
//波特率校准反推处DLL和DLH外设时钟主频/设置波特率/过采样模式)-1
divisor_value = (uint16_t)((uint32_t)(APB_Clock_Freq / uart_paraX->UART_BaudRate / overSamp_mode) - 1);
CMSDK_UART->DLL = (uint8_t)(divisor_value & 0x00FF);
CMSDK_UART->DLH = (uint8_t)((divisor_value & 0xFF00)>>8);
/*FCR配置 FIFO control*/
CMSDK_UART->FCR |= (uart_paraX->FifoSetting->level <<6);//接收多少字节后触发中断
if(uart_paraX->FifoSetting->FIFO_Enable == 1)
{
CMSDK_UART->FCR |= (1);
}
//配置停止位
CMSDK_UART->LCR &= ~(0x01 << 2);
CMSDK_UART->LCR |= uart_paraX->stop_len<<2;
//配置数据位
CMSDK_UART->LCR &= ~(0x03 << 0);
CMSDK_UART->LCR |= uart_paraX->Word_len<<0;
//配置是否启用校验位
CMSDK_UART->LCR &= ~(0x01 << 3);
CMSDK_UART->LCR |= uart_paraX->Parity_EN<<3;
//启用校验位
if(uart_paraX->Parity_EN==Parity_SET)
{
CMSDK_UART->LCR &= ~(0x03 << 4);
CMSDK_UART->LCR |= uart_paraX->Even_EN<<4;
CMSDK_UART->LCR |= uart_paraX->Stick_EN<<5;
}
/*MCR自动流控配置*/
if(uart_paraX->UART_HardwareFlowControl == 1)
{
CMSDK_UART->MCR |= (1<<5);
}
/*电源管理寄存器PMU 的TXRST和RXRST设置,不需要设置*/
}
/*UART 的中断设置*/
void UART_ITConfig(CMSDK_UART_TypeDef *CMSDK_UART, UART_ITStructure* uart_paraX)
{
if(CMSDK_UART == CMSDK_UART1){
NVIC_DisableIRQ(UART1_IRQn);//Disable NVIC interrupt
NVIC_ClearPendingIRQ(UART1_IRQn);//Clear Pending NVINVIC_EnableIRQ(UART1_IRQn);//Enable NVIC interrupt
}
else if(CMSDK_UART == CMSDK_UART0){
NVIC_DisableIRQ(UART0_IRQn);//Disable NVIC interrupt
NVIC_ClearPendingIRQ(UART0_IRQn);//Clear Pending NVIC interrupt
}
/*IER配置中断使能寄存器*/
CMSDK_UART->IER |= (uart_paraX->UartIntModel);
if(CMSDK_UART == CMSDK_UART1){
NVIC_EnableIRQ(UART1_IRQn);
}
else if(CMSDK_UART == CMSDK_UART0){
NVIC_EnableIRQ(UART0_IRQn);
}
}
unsigned char UartPutc(CMSDK_UART_TypeDef *CMSDK_UART ,unsigned char my_ch)
{
while (UARTLine_THREmpty(CMSDK_UART) == 0x0);
WRITE_UART_THRBuff(CMSDK_UART,my_ch);
return (my_ch);
}
//串口发送一定字节的数据
void Uart_Send(CMSDK_UART_TypeDef *CMSDK_UART ,uint8_t *data, uint8_t len)
{
uint8_t t;
for(t=0;t<len;t++) //循环发送数据
{
while(UARTLine_THREmpty(CMSDK_UART) == 0x0);//等待发送结束
WRITE_UART_THRBuff(CMSDK_UART,data[t]);
}
while(UARTLine_THREmpty(CMSDK_UART) == 0x0);//等待发送结束
}
/*
1 线INT_RCV_LINE_STATUS
break
LSR break
2 INT_RCV_DATA_AVAILABLE
FIFO模式下 fifo模式下访FIFO ,
FIFO模式下RBR被读取 FIFO模式下FIFO低于触发阈值被清除
3 INT_CHAR_TIMEOUT_INDICATION
FIFO模式有效 FIFO FIFO中至少有一个字符
11FIFO中被读出 2FIFO 3PMU寄存器中的URRST 1
4 THR INT_THR_EMPTY
FIFO模式下 THR空 FIFO模式下FIFO空
THR
*/
void UART0_Handler(void) {
uint8_t rev_data = 0;
NVIC_ClearPendingIRQ(UART0_IRQn);
//接收线中断 有错误或者break
if(UART_INT_TYPE(CMSDK_UART0) == INT_RCV_LINE_STATUS) {
CMSDK_UART0->IER &= ~CMSDK_UART_IER_RLSI_EN_Msk;
}
//数据就绪中断
//接收超时中断
if((UART_INT_TYPE(CMSDK_UART0) == INT_RCV_DATA_AVAILABLE) || (UART_INT_TYPE(CMSDK_UART0) == INT_CHAR_TIMEOUT_INDICATION))
{
CMSDK_UART0->IER &= ~CMSDK_UART_IER_RDAI_EN_Msk;
rev_data = CMSDK_UART0->RBR;
UartPutc(CMSDK_UART0,rev_data);
CMSDK_UART0->IER |= CMSDK_UART_IER_RDAI_EN_Msk;
}
return;
}
2025-09-30 14:07:39 +08:00
// 外部变量声明在main.c中定义
uint8_t uart_rx_buffer[64];
uint8_t uart_rx_count;
volatile uint8_t uart_data_ready;
// 外部函数声明
extern uint8_t ParseUART_EMS_Packet(uint8_t *data, uint16_t length, void *packet);
extern void UpdateEMS_ConfigFromUART(void *packet);
// 数据包结构体定义
void UART1_Handler(void) {
uint8_t rev_data = 0;
2025-09-30 14:07:39 +08:00
uint32_t ParamNumber = 0;
// 清除NVIC中断挂起位
NVIC_ClearPendingIRQ(UART1_IRQn);
2025-09-30 14:07:39 +08:00
// 检查中断类型
uint8_t int_type = UART_INT_TYPE(CMSDK_UART1);
// 接收线中断 - 有错误或者break
if(int_type == INT_RCV_LINE_STATUS) {
// 读取LSR寄存器清除错误状态
uint32_t lsr = CMSDK_UART1->LSR;
(void)lsr; // 避免未使用变量警告
}
2025-09-30 14:07:39 +08:00
// 数据就绪中断或接收超时中断
if((int_type == INT_RCV_DATA_AVAILABLE) || (int_type == INT_CHAR_TIMEOUT_INDICATION)) {
ParamNumber = (CMSDK_UART1->FSR >> 16) & 0x1f;
for(uint32_t i = 0; i < ParamNumber; i++) {
rev_data = CMSDK_UART1->RBR; // 把接收到的数据取出来
// 将数据存储到缓冲区
if(uart_rx_count < sizeof(uart_rx_buffer)) {
uart_rx_buffer[uart_rx_count] = rev_data;
uart_rx_count++;
} else {
// 缓冲区溢出,重置
uart_rx_count = 0;
}
UartPutc(CMSDK_UART1, rev_data); // 把接收到的数据再发回去
}
// 检查是否收到完整数据包19字节
if(uart_rx_count >= 19) {
//printf("1");
// 解析数据包
UART_EMS_Packet_t ems_packet;
if(ParseUART_EMS_Packet(uart_rx_buffer, uart_rx_count, &ems_packet)) {
// 更新电刺激配置
UpdateEMS_ConfigFromUART(&ems_packet);
} else {
}
// 清除缓冲区
uart_rx_count = 0;
}
}
return;
}
2025-09-30 14:07:39 +08:00