10 静态全局指针有初始值和无初始值有什么区别?

一般韦老师的写法是先定义一个全局的static指针,在外设初始化函数时先对指针变量赋值,然后对指针操作, 从而达到控制外设寄存器的目的。

我跟着课程学习裸机uart这一章,没有全抄韦老师的代码,只是定义指针的时候赋初始值,然后整个程序就不按预期运行了。

(不按预期运行就是指串口初始化不成功,导致没有任何信息打印出来。)

以下是可以运行的代码(循环打印字符, 在uart.c):

#include "uart.h"
static volatile unsigned int *IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA;//= (volatile unsigned int *)(0x020E0084);
static volatile unsigned int *IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA;//= (volatile unsigned int *)(0x020E0088);
static volatile unsigned int *IOMUXC_UART1_RX_DATA_SELECT_INPUT  ;//= (volatile unsigned int *)(0x020E0624);
void Uart_Init(void){
    
    IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA     = (volatile unsigned int *)(0x020E0084);
    IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA     = (volatile unsigned int *)(0x020E0088);
    IOMUXC_UART1_RX_DATA_SELECT_INPUT       = (volatile unsigned int *)(0x020E0624);
    
    // 关闭当前串口
    UART1->UCR1 &= ~1;
    // CCM_CSCDR1保持默认值
    // 使能UART1模块时钟
    //*CCM_CCGR5 |= 3 << 24;  // 默认使能 可以不用设置
    // 配置UART1_TX复用功能
    *IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA = 0;
    // 配置UART1_RX复用功能
    *IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA = 0;
    // 设置驱动UART1模块的引脚
    *IOMUXC_UART1_RX_DATA_SELECT_INPUT = 3;   // 从UART1_RX引脚作为UART1_RX的输入
    // 配置UART1_TX的硬件参数
    // IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA保持默认值
    // 配置UART1_RX的硬件参数
    // IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA保持默认值
    // 配置UART1的传输格式, 波特率
    UART1->UCR2 |= (1<<14) |(1<<5) |(1<<2)|(1<<1);
    // [14] 1: 忽略RTS引脚
    // [8]  0: 关闭奇偶校验位
    // [6]  0: 停止位1位
    // [5]  1: 数据长度1位
    // [2]  1: 发送使能
    // [1]  1: 接收使能
    UART1->UCR3 |= (1 << 2); // 芯片特色, 该位必须配置为1
    UART1->UFCR = 5 << 7;  // UART时钟 80MHz
    UART1->UBIR = 71;      // 115200波特率
    UART1->UBMR = 3124;    // 115200波特率
    // 使能串口
    UART1->UCR1 |= 1;
}
以下是不可以运行的代码(在uart_bk.c):
#include "uart.h"
static volatile unsigned int *IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA= (volatile unsigned int *)(0x020E0084);
static volatile unsigned int *IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA= (volatile unsigned int *)(0x020E0088);
static volatile unsigned int *IOMUXC_UART1_RX_DATA_SELECT_INPUT  = (volatile unsigned int *)(0x020E0624);
void Uart_Init(void){
    /*
    IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA     = (volatile unsigned int *)(0x020E0084);
    IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA     = (volatile unsigned int *)(0x020E0088);
    IOMUXC_UART1_RX_DATA_SELECT_INPUT       = (volatile unsigned int *)(0x020E0624);
    */
    // 关闭当前串口
    UART1->UCR1 &= ~1;
    // CCM_CSCDR1保持默认值
    // 使能UART1模块时钟
    //*CCM_CCGR5 |= 3 << 24;  // 默认使能 可以不用设置
    // 配置UART1_TX复用功能
    *IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA = 0;
    // 配置UART1_RX复用功能
    *IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA = 0;
    // 设置驱动UART1模块的引脚
    *IOMUXC_UART1_RX_DATA_SELECT_INPUT = 3;   // 从UART1_RX引脚作为UART1_RX的输入
    // 配置UART1_TX的硬件参数
    // IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA保持默认值
    // 配置UART1_RX的硬件参数
    // IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA保持默认值
    // 配置UART1的传输格式, 波特率
    UART1->UCR2 |= (1<<14) |(1<<5) |(1<<2)|(1<<1);
    // [14] 1: 忽略RTS引脚
    // [8]  0: 关闭奇偶校验位
    // [6]  0: 停止位1位
    // [5]  1: 数据长度1位
    // [2]  1: 发送使能
    // [1]  1: 接收使能
    UART1->UCR3 |= (1 << 2); // 芯片特色, 该位必须配置为1
    UART1->UFCR = 5 << 7;  // UART时钟 80MHz
    UART1->UBIR = 71;      // 115200波特率
    UART1->UBMR = 3124;    // 115200波特率
    // 使能串口
    UART1->UCR1 |= 1;
}
两个文件生成的.dis文件反复看过了,主要是一个在bss段,一个在data段,但分析下来,没发现有什么问题,希望有同学可以帮忙看一下。
下面是整个工程的文件代码,在imx6ull上运行,make的时候用uart_bk.c替换uart.c就可以得到不能运行的.imx文件。

2020年11月13日更新
先让串口可以打印,然后通过串口查看使用uart_bk.c的方法定义的寄存器的地址以及赋值后值的情况,发现赋值没有成功,原因不清楚,代码如下:

#include "uart.h"

static volatile unsigned int *IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA= (volatile unsigned int *)(0x020E0084);
static volatile unsigned int *IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA;//= (volatile unsigned int *)(0x020E0088);
static volatile unsigned int *IOMUXC_UART1_RX_DATA_SELECT_INPUT  ;//= (volatile unsigned int *)(0x020E0624);
void Uart_Init(void){
    
    //IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA       = (volatile unsigned int *)(0x020E0084);
    IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA     = (volatile unsigned int *)(0x020E0088);
    IOMUXC_UART1_RX_DATA_SELECT_INPUT       = (volatile unsigned int *)(0x020E0624);
    
    // 关闭当前串口
    UART1->UCR1 &= ~1;
    // CCM_CSCDR1保持默认值
    // 使能UART1模块时钟
    //*CCM_CCGR5 |= 3 << 24;  // 默认使能 可以不用设置
    // 配置UART1_TX复用功能
    *IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA = 0;
    // 配置UART1_RX复用功能
    *IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA = 134;
    // 设置驱动UART1模块的引脚
    *IOMUXC_UART1_RX_DATA_SELECT_INPUT = 3;   // 从UART1_RX引脚作为UART1_RX的输入
    // 配置UART1_TX的硬件参数
    // IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA保持默认值
    // 配置UART1_RX的硬件参数
    // IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA保持默认值
    // 配置UART1的传输格式, 波特率
    UART1->UCR2 |= (1<<14) |(1<<5) |(1<<2)|(1<<1);
    // [14] 1: 忽略RTS引脚
    // [8]  0: 关闭奇偶校验位
    // [6]  0: 停止位1位
    // [5]  1: 数据长度1位
    // [2]  1: 发送使能
    // [1]  1: 接收使能
    UART1->UCR3 |= (1 << 2); // 芯片特色, 该位必须配置为1
    UART1->UFCR = 5 << 7;  // UART时钟 80MHz
    UART1->UBIR = 71;      // 115200波特率
    UART1->UBMR = 3124;    // 115200波特率
    // 使能串口
    UART1->UCR1 |= 1;
    if(IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA == (unsigned int *)(0X020E0088)){
        PutChar('Y');       // 实际运行时被打印
    }
    else{
        PutChar('N');
    }
    if(*((volatile unsigned int *)(0x020E0088)) == 134){
        PutChar('Z');
    }
    else{
        PutChar('X');       // 实际运行时被打印
    }
    if(*IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA == 134){
        PutChar('R');
    }
    else{
        PutChar('T');       // 实际运行时被打印
    }
    *((volatile unsigned int *)(0x020E0088)) = 134;
    if(*((volatile unsigned int *)(0x020E0088)) == 134){
        PutChar('Z');
    }
    else{
        PutChar('X');       // 实际运行时被打印
    }
}

void PutChar(int c){
    while(!((UART1->USR2) & (1 << 3)));
    UART1->UTXD = (unsigned char)c;
}


请先 登录 后评论

1 个回答

星星之火 - 嵌入式工程师
擅长:答疑助手

错误的方式在Uart_Init中把地址再打印一下看看

请先 登录 后评论
  • 2 关注
  • 0 收藏,88 浏览
  • ! ! 提出于 2020-11-11 21:56