【中微】BAT32G133 串行通信单元(SPI与UART)
本文最后更新于23 天前,其中的信息可能已经过时,如有错误请发送邮件到tudougin@163.com

1. 通用串行通信单元

通用串行通信单元的1个单元有4个串行通道,各通道能实现3线串行(SSPI)、UART的通信功能。BAT32G133功能分配如下:

单元通道用作SSP1功能用作UART功能
00SSP100(支持从机选择输入)UART0
01SSP101
02SSP110UART1
03SSP111
10SSP120UART2
11SSP121

在单元0的通道0和通道1使用UART0时,不能使用SSPI00和SSPI01,但是能使用通道2和通道3的SSPI10、UART1。

2. UART

当用作UART时,发送方(偶数通道)接收方(奇数通道)只能用于UART

2.1 UART功能

  1. 数据的发送和接收
    • 7位、8位或者9位的数据长度(注:只有UART0支持9位数据长度。)
    • MSB/LSB优先的选择
    • 发送和接收数据的电平设置(选择电平是否反相)
    • 奇偶校验位的附加、奇偶校验功能
    • 停止位的附加、停止位的检测功能
  2. 中断功能
    • 传送结束中断、缓冲器空中断
    • 帧错误、奇偶校验错误和溢出错误引起的错误中断
  3. 错误检测标志
    • 帧错误、奇偶校验错误、溢出错
image-20250527223725787

2.2 UART配置

2.2.1 配置串口参数

	SystemCoreClockUpdate();
	status = UART0_Init(SystemCoreClock, 19200);

库默认配置UART参数为8N1(8位数据位,无奇偶校验,1位停止位)、中断默认开启,可修改SCI0->SCR00SCI0->SCR01配置代码进行参数更改;

MD_STATUS UART0_Init(uint32_t freq, uint32_t baud)
{
    MD_STATUS status;

    CGC->PER0 |= CGC_PER0_SCI0EN_Msk;
    SCI0->SPS0 = (0 << SCI0_SPS0_PRS00_Pos) | (3 << SCI0_SPS0_PRS00_Pos);
    /* transmission channel */
    SCI0->SMR00 = _0020_SMRMN_DEFAULT_VALUE | _0000_SCI_CLOCK_SELECT_CK00 | _0000_SCI_CLOCK_MODE_CKS |
                  _0002_SCI_MODE_UART | _0000_SCI_TRANSFER_END;
    SCI0->SCR00 = _0004_SCRMN_DEFAULT_VALUE | _8000_SCI_TRANSMISSION | _0000_SCI_TIMING_1 | _0000_SCI_INTSRE_MASK |
                  _0000_SCI_PARITY_NONE | _0080_SCI_LSB | _0010_SCI_STOP_1 | _0003_SCI_LENGTH_8;//修改此处发送串口参数
    SCI0->SDR00 = _CE00_SCI_BAUDRATE_DIVISOR;
    /* reception channel */
    MISC->NFEN0 |= _01_SCI_RXD0_FILTER_ON;
    SCI0->SIR01 = _0004_SCI_SIRMN_FECTMN | _0002_SCI_SIRMN_PECTMN | _0001_SCI_SIRMN_OVCTMN;
    SCI0->SMR01 = _0020_SMRMN_DEFAULT_VALUE | _0000_SCI_CLOCK_SELECT_CK00 | _0000_SCI_CLOCK_MODE_CKS |
                  _0100_SCI_TRIGGER_RXD | _0000_SCI_EDGE_FALL | _0002_SCI_MODE_UART | _0000_SCI_TRANSFER_END;
    SCI0->SCR01 = _0004_SCRMN_DEFAULT_VALUE | _4000_SCI_RECEPTION | _0000_SCI_TIMING_1 | _0000_SCI_INTSRE_MASK |
                  _0000_SCI_PARITY_NONE | _0080_SCI_LSB | _0010_SCI_STOP_1 | _0003_SCI_LENGTH_8;//修改此处接收串口参数
    SCI0->SDR01 = _CE00_SCI_BAUDRATE_DIVISOR;
    /* output enable */
    SCI0->SO0 |= _0001_SCI_CH0_DATA_OUTPUT_1;
    SCI0->SOL0 &= (uint16_t)~_0001_SCI_CHANNEL0_INVERTED;
    SCI0->SOE0 |= _0001_SCI_CH0_OUTPUT_ENABLE;
    /* Set TxD0 pin */
    TXD0_PORT_SETTING();
    /* Set RxD0 pin */
    RXD0_PORT_SETTING();
    /* UART0 Start, Setting baud rate */
    status = UART0_BaudRate(freq, baud);
    return (status);
}

2.2.2 配置串口引脚

/* ToDo: You can allocate the TXD0 to any desired pins with PxxCFG register */
#define TXD0_PORT_SETTING() do{ \
        PORT->P24CFG = PTCFG_TXD0;  /* allocate TXD0 to P24 */ \
        PORT->PM2  &= ~(1 << 4);    /* P24 is used as TXD0 output */ \
        PORT->POM2 &= ~(1 << 4);    /* P24 is normal output mode */ \
        PORT->PMC2 &= ~(1 << 4);    /* P24 digital function */ \
}while(0)

/* ToDo: You can allocate the RXD0 to any desired pins with PxxCFG register */
#define RXD0_PORT_SETTING() do{ \
        PORT->P23CFG = PTCFG_RXD0;  /* allocate RXD0 to P23 */ \
        PORT->PM2  |=  (1 << 3);    /* P23 is used as RXD0 input */ \
        PORT->PMC2 &= ~(1 << 3);    /* P23 digital function */ \
}while(0)

2.2.3 开启/关闭串口中断

UART0_Start();
UART0_Stop();

2.3 中断处理

2.3.1 接收中断

官方提供的库函数完成以下功能:接收串口数据,检查错误,存入缓冲区,并在完成或异常时调用对应的回调函数。但未在程序中发现g_uart0_rx_length 、g_uart0_rx_count的具体数值,可能仍需完善相关代码。比如实现128字节定长处理、发送数据以”\r\n”结束或者50ms内无数据则接收完成等

void uart0_interrupt_receive(void)
{
    volatile uint8_t rx_data;
    volatile uint8_t err_type;
    
    INTC_ClearPendingIRQ(SR0_IRQn);
    err_type = (uint8_t)(SCI0->SSR01 & 0x0007U);
    SCI0->SIR01 = (uint16_t)err_type;

    if (err_type != 0U)
    {
        uart0_callback_error(err_type);
    }
    
    rx_data = SCI0->RXD0;

    if (g_uart0_rx_length > g_uart0_rx_count)
    {
        *gp_uart0_rx_address = rx_data;
        gp_uart0_rx_address++;
        g_uart0_rx_count++;

        if (g_uart0_rx_length == g_uart0_rx_count)
        {
            uart0_callback_receiveend();
        }
    }
    else
    {
        uart0_callback_softwareoverrun(rx_data);
    }
}

2.3.2 发送中断

官方提供的库函数实现用于一个字节一个字节发送数据的功能。但程序仍有缺失部分,即gp_uart0_tx_address、g_uart0_tx_count相关部分的赋值,需要再编写相关的函数设置:

void uart0_interrupt_send(void)
{
    INTC_ClearPendingIRQ(ST0_IRQn);
    if (g_uart0_tx_count > 0U)
    {
        SCI0->TXD0 = *gp_uart0_tx_address;
        gp_uart0_tx_address++;
        g_uart0_tx_count--;
    }
    else
    {
        uart0_callback_sendend();
    }
}

3. SPI

与主控设备输出的串行时钟(SCK)同步进行数据的发送和接收。这是使用1条串行时钟(SCK)、1条发送串行数据(SO)和1条接收串行数据(SI)共3条通信线进行通信的时钟同步通信接口。

3.1 SPI功能

  1. 数据的发送和接收
    • 7位或者8位的数据长度
    • 发送和接收数据的相位控制
    • MSB/LSB优先的选择
  2. 时钟控制
    • 主控或者从属的选择
    • 输入/输出时钟的相位控制
    • 由预分频器和通道内部计数器产生的传送周期
    • 最大传送速率
      • 主控通信:最大值Fclk/2
      • 从属通信:最大值Fmck/6
  3. 中断功能
    • 传送结束中断、缓冲器空中断
  4. 错误检测标志
    • 溢出错误
image-20250527223750948

3.2 SPI配置(主机)

3.2.1 配置SPI模式

/* @param  mode
*             - SPI_MODE_0: CPOL = 0, CPHA = 0; i.e. DAP = 1, CKP = 1
*             - SPI_MODE_1: CPOL = 0, CPHA = 1; i.e. DAP = 0, CKP = 1
*             - SPI_MODE_2: CPOL = 1, CPHA = 0; i.e. DAP = 1, CKP = 0
*             - SPI_MODE_3: CPOL = 1, CPHA = 1; i.e. DAP = 0, CKP = 0
*/
SPI10_MasterInit(SPI_MODE_0);

对于SPI的格式,官方默认使用8位、MSB的格式,使用者可以在代码中进行修改

void SPI10_MasterInit(spi_mode_t mode)
{
    CGC->PER0 |= CGC_PER0_SCI0EN_Msk;
    SCI0->ST0 |= _0004_SCI_CH2_STOP_TRG_ON;
    SCI0->SPS0 &= ~SCI0_SPS0_PRS01_Msk;
    SCI0->SPS0 |= (0 << SCI0_SPS0_PRS01_Pos);
    SCI0->SIR02 = _0004_SCI_SIRMN_FECTMN | _0002_SCI_SIRMN_PECTMN | _0001_SCI_SIRMN_OVCTMN;
    SCI0->SMR02 = _0020_SMRMN_DEFAULT_VALUE | _8000_SCI_CLOCK_SELECT_CK01 | _0000_SCI_CLOCK_MODE_CKS |
                  _0000_SCI_TRIGGER_SOFTWARE | _0000_SCI_MODE_SPI | _0000_SCI_TRANSFER_END;
    SCI0->SCR02 = _0004_SCRMN_DEFAULT_VALUE | _C000_SCI_RECEPTION_TRANSMISSION | mode | _0000_SCI_INTSRE_MASK |
                  _0000_SCI_PARITY_NONE | _0000_SCI_MSB | _0000_SCI_STOP_NONE | _0003_SCI_LENGTH_8;//参数修改这里
#ifdef HIGH_SPEED_SPI
		//SCI0->SDR02 = 1 << 9;  /* fMCK/(1+n)x2 = fMCK/4 */
    	//SCI0->SDR02 = 2 << 9;  /* fMCK/(1+n)x2 = fMCK/6 */
	  	//SCI0->SDR02 = 3 << 9;  /* fMCK/(1+n)x2 = fMCK/8 */
		SCI0->SDR02 = 4 << 9;  /* fMCK/(1+n)x2 = fMCK/10 */
		//SCI0->SDR02 = 5 << 9;  /* fMCK/(1+n)x2 = fMCK/12 */
#else
    SCI0->SDR02 = _CE00_SCI_BAUDRATE_DIVISOR;
#endif
    /* Set output enable */
    if ((mode == SPI_MODE_0) || (mode == SPI_MODE_1))
    {
        SCI0->SO0 &= ~_0400_SCI_CH2_CLOCK_OUTPUT_1;
    }
    if ((mode == SPI_MODE_2) || (mode == SPI_MODE_3))
    {
        SCI0->SO0 |= _0400_SCI_CH2_CLOCK_OUTPUT_1;
    }
    SCI0->SOE0 |= _0004_SCI_CH2_OUTPUT_ENABLE;
    /* Set SSn pin */
    SS10_PORT_SETTING();
    /* Set SCLK10 pin */
    SCLKO10_PORT_SETTING();
    /* Set SDI10 pin */
    SDI10_PORT_SETTING();
    /* Set SDO10 pin */
    SDO10_PORT_SETTING();
}

3.2.2 配置SPI引脚

/* ToDo: You can allocate the SS10 to any desired pins */
#define SS10_PORT_SETTING() do{ \
        PORT->P10CFG = 0x00;         /* P10 default GPIO function */ \
        PORT->P1   |=  (1 << 0);     /* P10 output high level */ \
        PORT->PM1  &= ~(1 << 0);     /* P10 is used as SS01 input */ \
}while(0)

/* ToDo: You can allocate the SS10 to any desired pins */
#define SS10_PORT_SET() do{ \
        PORT->P1   |=  (1 << 0);     /* P10 output high level */ \
}while(0)

/* ToDo: You can allocate the SS10 to any desired pins */
#define SS10_PORT_CLR() do{ \
        PORT->P1   &= ~(1 << 0);     /* P10 output low level */ \
}while(0)

/* ToDo: You can allocate the SCLKI10 to any desired pins with PxxCFG register */
#define SCLKI10_PORT_SETTING() do{ \
        PORT->P35CFG = PTCFG_SCLK10; /* allocate SCLK10 to P35 */ \
        PORT->PM3  |=  (1 << 5);     /* P35 is used as SCLK10 input */ \
        PORT->PMC3 &= ~(1 << 5);     /* P35 digital function */ \
}while(0)

/* ToDo: You can allocate the SCLKO10 to any desired pins with PxxCFG register */
#define SCLKO10_PORT_SETTING() do{ \
        PORT->P35CFG = PTCFG_SCLK10;/* allocate SCLK10 to P35 */ \
        PORT->PM3  &= ~(1 << 5);    /* P35 is used as SCLK10 output */ \
        PORT->POM3 &= ~(1 << 5);    /* P35 is normal output mode */ \
        PORT->PMC3 &= ~(1 << 5);    /* P35 digital function */ \
}while(0)

/* ToDo: You can allocate the SDO10 to any desired pins with PxxCFG register */
#define SDO10_PORT_SETTING() do{ \
        PORT->P37CFG = PTCFG_SDO10; /* allocate SDO10 to P37 */ \
        PORT->PM3  &= ~(1 << 7);    /* P37 is used as SDO10 output */ \
        PORT->POM3 &= ~(1 << 7);    /* P37 is normal output mode */ \
        PORT->PMC3 &= ~(1 << 7);    /* P37 digital function */ \
}while(0)

/* ToDo: You can allocate the SDI10 to any desired pins with PxxCFG register */
#define SDI10_PORT_SETTING() do{ \
        PORT->P36CFG = PTCFG_SDI10; /* allocate SDI10 to P36 */ \
        PORT->PM3  |=  (1 << 6);    /* P36 is used as SDI10 input */ \
        PORT->PMC3 &= ~(1 << 6);    /* P36 digital function */ \
}while(0)

3.2.3 SPI中断开启/关闭

SPI10_Start();
SPI10_Stop();

3.3 SPI数据收发

uint8_t mtx_buf[] = {0xA5, 0x5A, 0xCC, 0x33, 0x3C, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
uint8_t mrx3_buf[13];

SPI10_MasterSend(mtx_buf, sizeof(mtx_buf));
SPI10_MasterReceive(mrx3_buf, sizeof(mrx3_buf));
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇