stm8 uart tx中断问题

问题描述

我正在通过中断将 STM8S103F3 编程到 UART 上的 TX。我知道在“传输数据寄存器空中断”之后写入 DR 将启动另一个 TX,所以我在我的 ISR 中有这个。但它只有在我的主循环旋转等待中断时才有效。如果它在 nop 上旋转,则只发送第一个字符 - 好像在 ISR 中写入 DR 不会产生后续中断。

使用 SDCC 编译器。

sdcc -mstm8 -o build\uart.hex uart.c

#include <stdint.h>
#include <stdlib.h>
#include "stm8.h"

#define DEBUG_BUF_SIZE 10
char debugBuf[DEBUG_BUF_SIZE];
volatile unsigned char *debugPtr;

// UART Tx interrupt
void TX_complete(void) __interrupt(UART_TX_COMPLETE) {
    if(*debugPtr != 0) {
        UART1_DR = *debugPtr++;
    } 
}

void log(char *msg)
{
    unsigned char i = 0;

    UART1_CR2 &= ~UART_CR2_TIEN;
    for(; msg[i] != 0 && i<DEBUG_BUF_SIZE-1; i++) {
        debugBuf[i] = msg[i];
    }
    debugBuf[i] = 0;
    debugPtr = debugBuf;
    UART1_CR2 |= UART_CR2_TIEN;

    // Write to DR will start tx
    UART1_DR = *debugPtr++;
}


int main(void)
{
    // UART 115K2 baud,interrupt driven tx
    // UART1_CR1,UART_CR3 reset values are 8N1
    UART1_BRR2 = 0x0B;
    UART1_BRR1 = 0x08;
    UART1_CR2 |= UART_CR2_TEN | UART_CR2_TIEN;

    /* Set clock to full speed (16 Mhz) */
    CLK_CKDIVR = 0;

    log("Run\r\n");

    while(1) {
        // Only the first char is txed if nop is used
        nop();
        // But all chars txed if wfi is used
        // wfi();
    }
}

解决方法

请参阅第 12.9.1 章中 stm8 的参考手册(我使用 CD00218714),您将看到 CPU 条件代码寄存器的默认值(复位后)为 0x28 - 这意味着在启动后您的 mcu 将在中断级别 3 下工作并且所有软件中断都被禁止,只有RESET和TRAP可以工作。

根据程序手册(我用的是CD00161709)指令WFI将中断级别改为0级,你的USART软件中断就可以工作了。

您需要在初始化代码之后(行 # User model protected static function booted() { static::deleting(function ($user) { $user->superiorUsers()->sync([]); $user->inferiorUsers()->sync([]); }); } public function superiorUsers() { return $this->belongsToMany( 'App\Models\User','user_user','user_id','superior_id' ); } public function inferiorUsers() { return $this->belongsToMany( 'App\Models\User','superior_id','user_id' ); } 之后)插入 asm("rim"); - 这将使您的代码适用于基于 CLK_CKDIVR = 0; 的主循环。