533 lines
16 KiB
C
533 lines
16 KiB
C
#include "ch438q.h"
|
||
#include "fsmc.h"
|
||
#include "ht1200m.h"
|
||
#include "tcpserverc.h"
|
||
#define CH438_CLK 1843200 /* CH438的内部时钟频率,默认外部晶振的12分频 */
|
||
|
||
const uint8_t offsetadd[] = {
|
||
0x00,
|
||
0x10,
|
||
0x20,
|
||
0x30,
|
||
0x08,
|
||
0x18,
|
||
0x28,
|
||
0x38,
|
||
}; /* 串口号的偏移地址 */
|
||
const uint8_t Interruptnum[] = {
|
||
0x01,
|
||
0x02,
|
||
0x04,
|
||
0x08,
|
||
0x10,
|
||
0x20,
|
||
0x40,
|
||
0x80,
|
||
}; /* SSR寄存器中断号对应值 */
|
||
|
||
ch438_uart_data_t ch438_uart_data[16] = {0};
|
||
uint8_t receive_data_len;
|
||
uint32_t uart_times[TCP_MAX] = {0};
|
||
uint8_t ch438_1_int_flag = 0;
|
||
uint8_t ch438_2_int_flag = 0;
|
||
static void ch438_tranconfig(uint8_t uart_num);
|
||
static void ch438_set_baudrate(uint8_t uart_num, uint32_t baudrate);
|
||
|
||
/**
|
||
* @brief 配置串口通信参数
|
||
*
|
||
* 设置串口通讯的格式,8个数据位,1个停止位,1个校验位,奇校验,并设置FIFO模式,触发点为112个字节。
|
||
*
|
||
* @param uart_num 串口编号
|
||
*/
|
||
void ch438_tranconfig(uint8_t uart_num)
|
||
{
|
||
uint8_t ch438_num = 0;
|
||
if (uart_num < 8)
|
||
{
|
||
ch438_num = CH438_CHIP0;
|
||
}
|
||
else
|
||
{
|
||
ch438_num = CH438_CHIP1;
|
||
uart_num -= 8;
|
||
}
|
||
// 设置串口通讯的格式,8个数据位,1个停止位,1个校验位,奇校验
|
||
ch438_write_reg(ch438_num, offsetadd[uart_num] | REG_LCR_ADDR, BIT_LCR_PAREN | BIT_LCR_WORDSZ1 | BIT_LCR_WORDSZ0, 1);
|
||
/* 设置FIFO模式,触发点为112个字节 */
|
||
ch438_write_reg(ch438_num, offsetadd[uart_num] | REG_FCR_ADDR, BIT_FCR_RECVTG0 | BIT_FCR_RECVTG1 | BIT_FCR_FIFOEN, 1);
|
||
}
|
||
|
||
/**
|
||
* @brief 设置CH438 UART的波特率
|
||
*
|
||
* 通过修改CH438 UART的波特率寄存器来设置指定UART的波特率。
|
||
*
|
||
* @param uart_num UART编号
|
||
* @param baudrate 需要设置的波特率
|
||
*/
|
||
static void ch438_set_baudrate(uint8_t uart_num, uint32_t baudrate)
|
||
{
|
||
uint8_t dlab = 0;
|
||
uint16_t bandspeed;
|
||
uint8_t ch438_num = 0;
|
||
if (uart_num < 8)
|
||
{
|
||
ch438_num = CH438_CHIP0;
|
||
}
|
||
else
|
||
{
|
||
ch438_num = CH438_CHIP1;
|
||
uart_num -= 8;
|
||
}
|
||
dlab = ch438_read_reg(ch438_num, offsetadd[uart_num] | REG_LCR_ADDR, 1);
|
||
dlab |= 0x80; // 置LCR寄存器的DLAB位为1
|
||
ch438_write_reg(ch438_num, offsetadd[uart_num] | REG_LCR_ADDR, dlab, 1);
|
||
|
||
bandspeed = CH438_CLK / 16 / baudrate;
|
||
ch438_write_reg(ch438_num, offsetadd[uart_num] | REG_DLL_ADDR, (uint8_t)bandspeed, 1);
|
||
ch438_write_reg(ch438_num, offsetadd[uart_num] | REG_DLM_ADDR, (uint8_t)(bandspeed >> 8), 1);
|
||
|
||
dlab &= 0x7F; // 置LCR寄存器的DLAB位为0
|
||
ch438_write_reg(ch438_num, offsetadd[uart_num] | REG_LCR_ADDR, dlab, 1);
|
||
}
|
||
|
||
/**
|
||
* @brief 向CH438寄存器写入数据
|
||
*
|
||
* 该函数用于向CH438芯片的指定寄存器写入指定大小的数据。
|
||
*
|
||
* @param addr 要写入的寄存器地址
|
||
* @param data 要写入的数据
|
||
* @param size 要写入的数据大小(以字节为单位)
|
||
*/
|
||
void ch438_write_reg(uint8_t ch438_num, uint8_t addr, uint8_t data, uint8_t size)
|
||
{
|
||
if (ch438_num == CH438_CHIP0)
|
||
{
|
||
uint32_t *address = (uint32_t *)(0x60000000 + addr);
|
||
HAL_SRAM_Write_8b(&hsram1, address, &data, size);
|
||
}
|
||
else if (ch438_num == CH438_CHIP1)
|
||
{
|
||
uint32_t *address = (uint32_t *)(0x64000000 + addr);
|
||
HAL_SRAM_Write_8b(&hsram2, address, &data, size);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 从CH438的寄存器中读取数据
|
||
*
|
||
* 从指定的地址读取指定大小的数据。
|
||
*
|
||
* @param addr 寄存器地址
|
||
* @param size 要读取的数据大小(以字节为单位)
|
||
*
|
||
* @return 读取到的数据
|
||
*/
|
||
uint8_t ch438_read_reg(uint8_t ch438_num, uint8_t addr, uint8_t size)
|
||
{
|
||
uint8_t data = 0;
|
||
if (ch438_num == CH438_CHIP0)
|
||
{
|
||
uint32_t *address = (uint32_t *)(0x60000000 + addr);
|
||
HAL_SRAM_Read_8b(&hsram1, address, &data, size);
|
||
}
|
||
else if (ch438_num == CH438_CHIP1)
|
||
{
|
||
uint32_t *address = (uint32_t *)(0x64000000 + addr);
|
||
HAL_SRAM_Read_8b(&hsram2, address, &data, size);
|
||
}
|
||
return data;
|
||
}
|
||
|
||
/**
|
||
* @brief 重置所有UART
|
||
*
|
||
* 该函数用于重置所有UART设备。
|
||
*
|
||
* @return 无
|
||
*/
|
||
void ch438_reset_all_uart(void)
|
||
{
|
||
for (uint8_t i = 0; i < 8; i++)
|
||
{
|
||
ch438_write_reg(CH438_CHIP0, offsetadd[CH438_UART0 + i] | REG_IER_ADDR, BIT_IER_RESET, 1);
|
||
ch438_write_reg(CH438_CHIP1, offsetadd[CH438_UART0 + i] | REG_IER_ADDR, BIT_IER_RESET, 1);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 关闭指定UART的电源
|
||
*
|
||
* 关闭指定UART的电源,使UART进入低功耗模式。
|
||
*
|
||
* @param uart_num UART编号,取值范围为0到3
|
||
*/
|
||
void ch438_close_uart(uint8_t uart_num)
|
||
{
|
||
uint8_t ch438_num = 0;
|
||
if (uart_num < 8)
|
||
{
|
||
ch438_num = CH438_CHIP0;
|
||
}
|
||
else
|
||
{
|
||
ch438_num = CH438_CHIP1;
|
||
uart_num -= 8;
|
||
}
|
||
ch438_write_reg(ch438_num, offsetadd[uart_num] | REG_IER_ADDR, BIT_IER_LOWPOWER, 1);
|
||
}
|
||
|
||
/**
|
||
* @brief 关闭所有UART串口
|
||
*
|
||
* 关闭CH438芯片上的所有UART串口。
|
||
*
|
||
* 具体操作是向CH438的IER寄存器(中断使能寄存器)写入特定值,
|
||
* 将SLP(休眠模式使能位)和LOWPOWER(低功耗模式使能位)同时设置为1,
|
||
* 以关闭时钟振荡器并使所有UART串口进入休眠状态。
|
||
*/
|
||
void ch438_close_all_uart(void)
|
||
{
|
||
ch438_write_reg(CH438_CHIP0, offsetadd[CH438_UART0] | REG_IER_ADDR, BIT_IER_LOWPOWER | BIT_IER_SLP, 1); // 数据手册描述:SLP和LOWPOWER同时为1,关闭时钟振荡器,所有串口进入休眠
|
||
ch438_write_reg(CH438_CHIP1, offsetadd[CH438_UART0] | REG_IER_ADDR, BIT_IER_LOWPOWER | BIT_IER_SLP, 1); // 数据手册描述:SLP
|
||
}
|
||
|
||
/**
|
||
* @brief 初始化UART通信
|
||
*
|
||
* 该函数用于初始化指定的UART端口,并设置其波特率。
|
||
*
|
||
* @param uart_num UART端口号
|
||
* @param baudrate 波特率
|
||
*/
|
||
void ch438_init_uart(uint8_t uart_num, uint32_t baudrate)
|
||
{
|
||
|
||
ch438_tranconfig(uart_num);
|
||
ch438_set_baudrate(uart_num, baudrate);
|
||
}
|
||
|
||
/**
|
||
* @brief 检查并返回中断标识寄存器(IIR)的值
|
||
*
|
||
* 该函数通过UART编号读取并返回中断标识寄存器(IIR)的值。
|
||
*
|
||
* @param uart_num UART编号,用于指定要读取的UART接口
|
||
*
|
||
* @return 返回中断标识寄存器(IIR)的值
|
||
*/
|
||
uint8_t ch438_check_iir_reg(uint8_t uart_num)
|
||
{
|
||
uint8_t ch438_num = 0;
|
||
if (uart_num < 8)
|
||
{
|
||
ch438_num = CH438_CHIP0;
|
||
}
|
||
else
|
||
{
|
||
ch438_num = CH438_CHIP1;
|
||
uart_num -= 8;
|
||
}
|
||
return ch438_read_reg(ch438_num, offsetadd[uart_num] | REG_IIR_ADDR, 1);
|
||
}
|
||
|
||
/**
|
||
* @brief 初始化CH438的配置
|
||
*
|
||
* 该函数用于初始化CH438芯片的配置,包括中断使能寄存器和调制解调器控制寄存器的设置。
|
||
*
|
||
* @param uart_num UART编号,用于指定要初始化的UART通道
|
||
*/
|
||
void ch438_init_config(uint8_t uart_num)
|
||
{
|
||
uint8_t ch438_num = 0;
|
||
if (uart_num < 8)
|
||
{
|
||
ch438_num = CH438_CHIP0;
|
||
}
|
||
else
|
||
{
|
||
ch438_num = CH438_CHIP1;
|
||
uart_num -= 8;
|
||
}
|
||
/* CH438打开BIT_IER_IETHRE会产生一个发送空中断 */
|
||
ch438_write_reg(ch438_num, offsetadd[uart_num] | REG_IER_ADDR, BIT_IER_IELINES | BIT_IER_IETHRE | BIT_IER_IERECV, 1);
|
||
ch438_check_iir_reg(uart_num);
|
||
ch438_write_reg(ch438_num, offsetadd[uart_num] | REG_MCR_ADDR, BIT_MCR_OUT2, 1);
|
||
}
|
||
|
||
void ch438_send_data(uint8_t uart_num, uint8_t *data, uint16_t len)
|
||
{
|
||
hart_ht1200m_rts_io_send(uart_num);
|
||
uint8_t ch438_num = 0;
|
||
data[len] = 0x00; // 因为发送数据RHART的RTS需要延时,这里用多一个字节的发送来代替延时
|
||
data[len + 1] = 0x00; // 因为发送数据RHART的RTS需要延时,这里用多两个字节的发送来代替延时
|
||
if (uart_num < 8)
|
||
{
|
||
ch438_num = CH438_CHIP0;
|
||
}
|
||
else
|
||
{
|
||
ch438_num = CH438_CHIP1;
|
||
uart_num -= 8;
|
||
}
|
||
for (uint8_t i = 0; i < len + 2; i++)
|
||
{
|
||
ch438_write_reg(ch438_num, offsetadd[uart_num] | REG_THR_ADDR, data[i], 1);
|
||
}
|
||
}
|
||
uint8_t ch438_recv_data(uint8_t uart_num, uint8_t *data)
|
||
{
|
||
uint8_t data_len = 0;
|
||
uint8_t *receive_data;
|
||
receive_data = data;
|
||
uint16_t time_out = 1000;
|
||
uint8_t ch438_num = 0;
|
||
if (uart_num < 8)
|
||
{
|
||
ch438_num = CH438_CHIP0;
|
||
}
|
||
else
|
||
{
|
||
ch438_num = CH438_CHIP1;
|
||
uart_num -= 8;
|
||
}
|
||
// 等待数据准备好
|
||
while ((ch438_read_reg(ch438_num, offsetadd[uart_num] | REG_LSR_ADDR, 1) & BIT_LSR_DATARDY) == 0)
|
||
{
|
||
time_out--;
|
||
if (time_out == 0)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
while ((ch438_read_reg(ch438_num, offsetadd[uart_num] | REG_LSR_ADDR, 1) & BIT_LSR_DATARDY))
|
||
{
|
||
*receive_data = ch438_read_reg(ch438_num, offsetadd[uart_num] | REG_RBR_ADDR, 1);
|
||
receive_data++;
|
||
data_len++;
|
||
if (data_len == 112)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
return data_len;
|
||
}
|
||
|
||
void ch438_interrupt_handler_ch438_chip_1(void)
|
||
{
|
||
uint8_t gInterruptStatus; /* 全局中断状态 */
|
||
uint8_t InterruptStatus; /* 独立串口中断状态 */
|
||
uint8_t i;
|
||
uint8_t ch438_num = CH438_CHIP0;
|
||
gInterruptStatus = ch438_read_reg(ch438_num, REG_SSR_ADDR, 1);
|
||
|
||
if (!gInterruptStatus)
|
||
{
|
||
return;
|
||
}
|
||
|
||
for (i = 0; i < 8; i++)
|
||
{
|
||
if (gInterruptStatus & Interruptnum[i]) /* 检测哪个串口发生中断 */
|
||
{
|
||
InterruptStatus = ch438_read_reg(ch438_num, offsetadd[i] | REG_IIR_ADDR, 1) & 0x0f; /* 读串口的中断状态 */
|
||
|
||
switch (InterruptStatus)
|
||
{
|
||
case INT_NOINT: /* 没有中断 */
|
||
break;
|
||
case INT_THR_EMPTY: /* THR空中断 */
|
||
hart_ht1200m_rts_io_receive(i);
|
||
break;
|
||
// case INT_RCV_OVERTIME: /* 接收超时中断 */
|
||
// ch438_uart_data[i].receive_data_length = ch438_recv_data(i, ch438_uart_data[i].receive_data_buff);
|
||
// // ch438_send_data(i, ch438_uart_data[i].receive_data_buff, ch438_uart_data[i].receive_data_length);
|
||
// if (tcp_echo_flags[i] == 1)
|
||
// {
|
||
// user_send_data_hart(i, ch438_uart_data[i].receive_data_buff, ch438_uart_data[i].receive_data_length);
|
||
// uart_times[i]++;
|
||
// }
|
||
// break;
|
||
// case INT_RCV_SUCCESS: /* 接收数据可用中断 */
|
||
// ch438_uart_data[i].receive_data_length = ch438_recv_data(i, ch438_uart_data[i].receive_data_buff);
|
||
// if (tcp_echo_flags[i] == 1)
|
||
// {
|
||
// user_send_data_hart(i, ch438_uart_data[i].receive_data_buff, ch438_uart_data[i].receive_data_length);
|
||
// uart_times[i]++;
|
||
// }
|
||
// break;
|
||
case INT_RCV_LINES: /* 接收线路状态中断 */
|
||
ch438_read_reg(ch438_num, offsetadd[i] | REG_LSR_ADDR, 1);
|
||
break;
|
||
case INT_MODEM_CHANGE: /* MODEM输入变化中断 */
|
||
ch438_read_reg(ch438_num, offsetadd[i] | REG_MSR_ADDR, 1);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void ch438_interrupt_handler_ch438_chip_2(void)
|
||
{
|
||
uint8_t gInterruptStatus; /* 全局中断状态 */
|
||
uint8_t InterruptStatus; /* 独立串口中断状态 */
|
||
uint8_t i;
|
||
uint8_t ch438_num = CH438_CHIP1;
|
||
gInterruptStatus = ch438_read_reg(ch438_num, REG_SSR_ADDR, 1);
|
||
|
||
if (!gInterruptStatus)
|
||
{
|
||
return;
|
||
}
|
||
|
||
for (i = 8; i < 16; i++)
|
||
{
|
||
if (gInterruptStatus & Interruptnum[i - 8]) /* 检测哪个串口发生中断 */
|
||
{
|
||
InterruptStatus = ch438_read_reg(ch438_num, offsetadd[i - 8] | REG_IIR_ADDR, 1) & 0x0f; /* 读串口的中断状态 */
|
||
|
||
switch (InterruptStatus)
|
||
{
|
||
case INT_NOINT: /* 没有中断 */
|
||
break;
|
||
case INT_THR_EMPTY: /* THR空中断 */
|
||
hart_ht1200m_rts_io_receive(i);
|
||
break;
|
||
// case INT_RCV_OVERTIME: /* 接收超时中断 */
|
||
// ch438_uart_data[i].receive_data_length = ch438_recv_data(i, ch438_uart_data[i].receive_data_buff);
|
||
// if (tcp_echo_flags[i] == 1)
|
||
// {
|
||
// user_send_data_hart(i, ch438_uart_data[i].receive_data_buff, ch438_uart_data[i].receive_data_length);
|
||
// uart_times[i]++;
|
||
// }
|
||
// break;
|
||
// case INT_RCV_SUCCESS: /* 接收数据可用中断 */
|
||
// ch438_uart_data[i].receive_data_length = ch438_recv_data(i, ch438_uart_data[i].receive_data_buff);
|
||
// if (tcp_echo_flags[i] == 1)
|
||
// {
|
||
// user_send_data_hart(i, ch438_uart_data[i].receive_data_buff, ch438_uart_data[i].receive_data_length);
|
||
// uart_times[i]++;
|
||
// }
|
||
// break;
|
||
case INT_RCV_LINES: /* 接收线路状态中断 */
|
||
ch438_read_reg(ch438_num, offsetadd[i - 8] | REG_LSR_ADDR, 1);
|
||
break;
|
||
case INT_MODEM_CHANGE: /* MODEM输入变化中断 */
|
||
ch438_read_reg(ch438_num, offsetadd[i - 8] | REG_MSR_ADDR, 1);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
void ch438_interrupt_handler_data_ch438_chip_1(void)
|
||
{
|
||
uint8_t gInterruptStatus; /* 全局中断状态 */
|
||
uint8_t InterruptStatus; /* 独立串口中断状态 */
|
||
uint8_t i;
|
||
uint8_t ch438_num = CH438_CHIP0;
|
||
gInterruptStatus = ch438_read_reg(ch438_num, REG_SSR_ADDR, 1);
|
||
|
||
if (!gInterruptStatus)
|
||
{
|
||
return;
|
||
}
|
||
|
||
for (i = 0; i < 8; i++)
|
||
{
|
||
if (gInterruptStatus & Interruptnum[i]) /* 检测哪个串口发生中断 */
|
||
{
|
||
InterruptStatus = ch438_read_reg(ch438_num, offsetadd[i] | REG_IIR_ADDR, 1) & 0x0f; /* 读串口的中断状态 */
|
||
|
||
switch (InterruptStatus)
|
||
{
|
||
|
||
case INT_RCV_OVERTIME: /* 接收超时中断 */
|
||
ch438_uart_data[i].receive_data_length = ch438_recv_data(i, ch438_uart_data[i].receive_data_buff);
|
||
if (tcp_echo_flags[i] == 1)
|
||
{
|
||
user_send_data_hart(i, ch438_uart_data[i].receive_data_buff, ch438_uart_data[i].receive_data_length);
|
||
uart_times[i]++;
|
||
}
|
||
break;
|
||
case INT_RCV_SUCCESS: /* 接收数据可用中断 */
|
||
ch438_uart_data[i].receive_data_length = ch438_recv_data(i, ch438_uart_data[i].receive_data_buff);
|
||
if (tcp_echo_flags[i] == 1)
|
||
{
|
||
user_send_data_hart(i, ch438_uart_data[i].receive_data_buff, ch438_uart_data[i].receive_data_length);
|
||
uart_times[i]++;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void ch438_interrupt_handler_data_ch438_chip_2(void)
|
||
{
|
||
uint8_t gInterruptStatus; /* 全局中断状态 */
|
||
uint8_t InterruptStatus; /* 独立串口中断状态 */
|
||
uint8_t i;
|
||
uint8_t ch438_num = CH438_CHIP1;
|
||
gInterruptStatus = ch438_read_reg(ch438_num, REG_SSR_ADDR, 1);
|
||
|
||
if (!gInterruptStatus)
|
||
{
|
||
return;
|
||
}
|
||
|
||
for (i = 8; i < 16; i++)
|
||
{
|
||
if (gInterruptStatus & Interruptnum[i - 8]) /* 检测哪个串口发生中断 */
|
||
{
|
||
InterruptStatus = ch438_read_reg(ch438_num, offsetadd[i - 8] | REG_IIR_ADDR, 1) & 0x0f; /* 读串口的中断状态 */
|
||
|
||
switch (InterruptStatus)
|
||
{
|
||
|
||
case INT_RCV_OVERTIME: /* 接收超时中断 */
|
||
ch438_uart_data[i].receive_data_length = ch438_recv_data(i, ch438_uart_data[i].receive_data_buff);
|
||
if (tcp_echo_flags[i] == 1)
|
||
{
|
||
user_send_data_hart(i, ch438_uart_data[i].receive_data_buff, ch438_uart_data[i].receive_data_length);
|
||
uart_times[i]++;
|
||
}
|
||
break;
|
||
case INT_RCV_SUCCESS: /* 接收数据可用中断 */
|
||
ch438_uart_data[i].receive_data_length = ch438_recv_data(i, ch438_uart_data[i].receive_data_buff);
|
||
if (tcp_echo_flags[i] == 1)
|
||
{
|
||
user_send_data_hart(i, ch438_uart_data[i].receive_data_buff, ch438_uart_data[i].receive_data_length);
|
||
uart_times[i]++;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
void ch438_init(void)
|
||
{
|
||
uint8_t i;
|
||
|
||
ch438_reset_all_uart();
|
||
HAL_Delay(250);
|
||
for (i = 0; i < 16; i++)
|
||
{
|
||
ch438_init_uart(i, 1200);
|
||
ch438_init_config(i);
|
||
hart_ht1200m_rts_io_receive(i);
|
||
}
|
||
}
|