打印
[LKS32 软件]

[LKS32MC037E开发板评测]+ UART点灯

[复制链接]
589|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 袁胜富 于 2023-2-28 10:15 编辑

#申请原创# 一、概述     

          在收到开发板之后,仔细研究发现LKS32MC037E芯片资源还是比较相对紧张的,如下图所示,引脚P1.8和P1.6,P1.6和P1.7公用一个引脚,程序都可以配置其为接收引脚,P1.8为发送引脚,P1.8其实为SWD两线下载中的SWCLK信号线,需要复用才可以用来做串口发送端口。
关于P1.8引脚做为复用串口0的发送端口,在芯片的Datasheet手册里有提到。LKS32MC03x_3P3N_DS_v2p47.pdf文件的的22章节 特殊IO复用里有说明,我截了如下图所示。默认状态是不开启复用,需要软件 向 SY S_ IO _CFG [ 写 0 开启复用。即芯片硬复位结束后,初始状态是 SWD 用途, SWD 的两个 IO 在芯片内部有上拉 芯片内部上拉电阻约为 10K)10K),在 IO用作 SWD 功能时,上拉默认开启且无法关闭。当 IO 用作 GPIO 时,上拉可以通过 GPIO1_PUE[8]和 GPIO1_PUE[9] 来控制。 芯片上电复位 30ms 内 P1.8 和 P1.9 固定为 SWD 功能,软件可以向SYS_ IO _CFG[ 写 0 ,但 IO 功能切换需要等待 30ms 后才生效。 30ms 使用 LRC 计数,由 于工艺原因存在一定偏差。
➢ 开启复用后, KEIL 等工具无法直接访 问芯片,即 Debug 和擦除下载功能均失效。若需要重新
下载程序,有两个方案。
⚫ 其一 ,建议使用凌鸥专用离线下载器擦除。软件开启复用的时间,建议保留 一定余量,例如
100ms 左右,保证离线下载器能擦除,防止死锁。余量的多少是保证离线下载器擦除的成功率。
余量越大,一次性擦除成功的概率越大。
⚫ 其二,程序内部有退出机制,例如某个其它 IO 电平发生变化 一般为输入 )),表明外界需要用
SWDIO ,软件重新配置,解除复用。此时,可以恢复 KEIL 的功能。

综上,我们使用P1.9端口复用为P1.8时需要在程序中注意,大概意思是上电后需要延时一段时间,在将P1.9通过软件配置程序(SYS_IO_CFG &= 0x00;    //swclk复用为UART0_TX)复用为P1.8.板子自带LED端口,端口为P1.4,网络标号FG,如下图所示。


二、评测内容

           通过上位机发送指令到UART0,UART0收到命令后执行关闭LED和开启LED。
三、代码展示

hardware_init.h文件
#define UART_BufferSize    128
typedef struct
{
        uint8_t RxBuffer[UART_BufferSize]; //数据接收缓冲区
        uint8_t CommandBuffer[UART_BufferSize]; //命令数据接收缓冲区
        uint16_t RxCnt;//数据接收长度
        uint8_t Rxfinish;//接收完成标志
}UART_DataType;
extern UART_DataType  uartData[1];

void UART_Printf(char *fmt,...);


hardware_init.c文件
UART_DataType  uartData[1] = {0};//数据接收结构
void GPIO_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_StructInit(&GPIO_InitStruct);
    //UART0初始化
   GPIO_StructInit(&GPIO_InitStruct);
   //uart0 P1_8 TXD
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
   GPIO_InitStruct.GPIO_Pin =  GPIO_Pin_8;
   GPIO_Init(GPIO1, &GPIO_InitStruct);
   //uart0 P1_7 RXD
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
  GPIO_InitStruct.GPIO_Pin =  GPIO_Pin_7;
  GPIO_Init(GPIO1, &GPIO_InitStruct);
  GPIO_PinAFConfig(GPIO1, GPIO_PinSource_8, AF4_UART);
  GPIO_PinAFConfig(GPIO1, GPIO_PinSource_7, AF4_UART);
}

void UART_init(void)
{
    UART_InitTypeDef UART_InitStruct;

    UART_StructInit(&UART_InitStruct);
    UART_InitStruct.BaudRate = 38400;                 /* 设置波特率38400 */
    UART_InitStruct.WordLength = UART_WORDLENGTH_8b;  /* 发送数据长度8位 */
    UART_InitStruct.StopBits = UART_STOPBITS_1b;
    UART_InitStruct.FirstSend = UART_FIRSTSEND_LSB;   /* 先发送LSB */
    UART_InitStruct.ParityMode = UART_Parity_NO;      /* 无奇偶校验 */
                UART_InitStruct.RXD_INV      = DISABLE;             /* RXD电平正常输出*/            
          UART_InitStruct.TXD_INV      = DISABLE;             /* TXD电平正常输出*/
          /*使能接收和发送完成中断*/
          UART_InitStruct.IRQEna       = UART_IRQEna_SendOver | UART_IRQEna_RcvOver; ;           
    UART_Init(UART0, &UART_InitStruct);

}
/**********************使用printf函数需要添加的函数*****************************************/

//标准库需要的支持函数                 
struct __FILE
{
   int handle;  
};

  FILE __stdout;   
       
//定义_sys_exit()以避免使用半主机模式   
void _sys_exit(int x)
{
     x = x;
}

//重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
    /* 发送一个字节数据到串口 */
    UART_SendData(UART0, (uint8_t)ch);
    /* 发送缓存状态位 */
    while ((UART0->STT & BIT0) == FALSE); //UART0->STT发送缓存状态位。

    return (ch);
}

void UART_Printf(char *fmt,...)
{
    char T1_Bufferr[128];
    uint16_t i,j;
    va_list ap;
    va_start(ap,fmt);
    vsprintf(T1_Bufferr,fmt,ap);
    va_end(ap);
    i=strlen(T1_Bufferr);
    for(j=0;j<i;j++)
    {
                        /* 发送一个字节数据到串口 */
                        UART_SendData(UART0, (uint8_t)T1_Bufferr[j]);
                        /* 发送缓存状态位 */
                        while ((UART0->STT & BIT0) == FALSE); //UART0->STT发送缓存状态位。
    }
}
main.c文件
int main(void)
{
        SoftDelay(10000);//留足程序下载时间
        SYS_IO_CFG &= 0x00;    //swclk复用为UART0_TX
        __disable_irq();      /* 关闭中断 中断总开关 */
        Hardware_init();      /* 硬件初始化 */
        sys_init();           /* 系统初始化 */
        __enable_irq();       /* 开启总中断 */
        LOOP:
        {
                if(uartData[0].Rxfinish == 1)
                {
                                printf("%s\r\n",uartData[0].CommandBuffer);
                                if(strstr((char*)uartData[0].CommandBuffer,"LED1_ON") != NULL)
                                {
                                        GPIO_WriteBit(GPIO1,GPIO_Pin_4,Bit_SET);
                                }
                                if(strstr((char*)uartData[0].CommandBuffer,"LED1_OFF") != NULL)
                                {
                                        GPIO_WriteBit(GPIO1,GPIO_Pin_4,Bit_RESET);
                                }
                                uartData[0].RxCnt = 0;
                                uartData[0].Rxfinish = 0;
                                memset(uartData[0].CommandBuffer,0,UART_BufferSize);
                                memset(uartData[0].RxBuffer,0,UART_BufferSize);
                }
        }
        goto LOOP;
}


tinterrput.c文件
u8 Uart0_Buff = 0;
void UART_IRQHandler(void)
{
        if (UART_GetIRQFlag(UART0, UART_IF_SendOver))    // 发送完成中断
        {
                UART_ClearIRQFlag(UART0, UART_IF_SendOver);  // 清除发送完成标志位
        }
        if (UART_GetIRQFlag(UART0, UART_IF_RcvOver))     // 接收完成中断
        {
                UART_ClearIRQFlag(UART0, UART_IF_RcvOver);         // 清除接收完成标志位
                Uart0_Buff = UART_ReadData(UART0);                         // 接收 1 Byte数据
                if(UART_BufferSize >= uartData[0].RxCnt)
                {
                        if(((Uart0_Buff == '!') || (uartData[0].RxBuffer[0] == '!')) && (uartData[0].Rxfinish == 0))
                        {
                                uartData[0].RxBuffer[uartData[0].RxCnt++] = Uart0_Buff;
                                if((uartData[0].RxBuffer[0] == '!') && (Uart0_Buff == '#'))
                                {
                                        strncpy((char*)uartData[0].CommandBuffer,(char*)uartData[0].RxBuffer+1,strlen((char*)uartData[0].RxBuffer)-2);
                                        uartData[0].Rxfinish = 1;
                                }
                        }
                }
                else
                {
                        uartData[0].RxCnt = 0;
                        uartData[0].Rxfinish = 0;
                        memset(uartData[0].RxBuffer,0,UART_BufferSize);
                }
        }
}



void SoftDelay(u32 cnt)
{
    volatile u32 t_cnt;
          int clcly = 1000;
    for(t_cnt = 0; t_cnt < cnt; t_cnt++)
    {
                        clcly = 1000;
                        while(clcly--)
                        {
        __nop();
                        }
    }
}

四、效果展示


上位机发送指令效果展示图片如下所示。

下位机(开发板)效果展示。


使用特权

评论回复
沙发
yangxiaor520| | 2023-3-1 08:45 | 只看该作者
小引脚封装,只能应用在对外设资源需求不高的场合了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

29

主题

149

帖子

2

粉丝