打印
[STM32L0]

STM32 L053之开发探幽

[复制链接]
520|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
cr315|  楼主 | 2022-12-9 10:08 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

1.开发环境选择

之前使用KEIL,一直都是5.00版本,使用起来STM32F系列的都妥妥的,都不知道为什么,在L053上面,遇到了各式各样的问题,先开始也没多想,觉得ST公司提供的文件非常非常的正确,可是在重新安装了KEIL5.10,KEIL5.12时,问题还是不停的出现

毫不犹豫,把遇到的其中几个分享一下-----首先是STM32PACK文件的问题,KEIL在安装的时候不知道抽了什么风,老是PACKINSTALLER无响应,在IMPORT之后好长时间没反应,一点击就无响应,使用器件就没有保障,遂选择一个类似的,唯一是把其中的固件库文件要修改其中一部分
好比来说,选择FLASH有不同,那就改变FLASH文件,ADC位数不同,那就该调整STM32L0XX_ADC.H
/**
  ******************************************************************************
  * @file    STM32L0xx_flash.h
  * @author  MCD Application Team
  * @version V1.3.0
  * @date    16-January-2014
  * @brief   This file contains all the functions prototypes for the FLASH
  *          firmware library.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        http://www.st.com/software_license_agreement_liberty_v2
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  ******************************************************************************
  */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32L0XX_FLASH_H
#define __STM32L0XX_FLASH_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "STM32L0xx.h"

/** @addtogroup STM32L0xx_StdPeriph_Driver
  * @{
  */

/** @addtogroup FLASH
  * @{
  */

/* Exported types ------------------------------------------------------------*/

/**
  * @brief  FLASH Status
  */
typedef enum
{
  FLASH_BUSY = 1,
  FLASH_ERROR_WRP,
  FLASH_ERROR_PROGRAM,
  FLASH_COMPLETE,
  FLASH_TIMEOUT
}FLASH_Status;

/* Exported constants --------------------------------------------------------*/

/** @defgroup FLASH_Exported_Constants
  * @{
  */

/** @defgroup FLASH_Latency
  * @{
  */
#define FLASH_Latency_0                ((uint32_t)0x00000000)  /*!< FLASH Zero Latency cycle */
#define FLASH_Latency_1                FLASH_ACR_LATENCY       /*!< FLASH One Latency cycle */

#define IS_FLASH_LATENCY(LATENCY) (((LATENCY) == FLASH_Latency_0) || \
                                   ((LATENCY) == FLASH_Latency_1))
/**
  * @}
  */

/** @defgroup FLASH_Interrupts
  * @{
  */

#define FLASH_IT_EOP                   FLASH_CR_EOPIE  /*!< End of programming interrupt source */
#define FLASH_IT_ERR                   FLASH_CR_ERRIE  /*!< Error interrupt source */
#define IS_FLASH_IT(IT) ((((IT) & (uint32_t)0xFFFFEBFF) == 0x00000000) && (((IT) != 0x00000000)))
/**
  * @}
  */


#define OB_STOP_NoRST                  ((uint8_t)0x02) /*!< No reset generated when entering in STOP */
#define OB_STOP_RST                    ((uint8_t)0x00) /*!< Reset generated when entering in STOP */
#define IS_OB_STOP_SOURCE(SOURCE) (((SOURCE) == OB_STOP_NoRST) || ((SOURCE) == OB_STOP_RST))
。。。

/** @defgroup FLASH_Option_Bytes_BOOT0SW
  * @{
  */

#define OB_BOOT0_SW                   ((uint8_t)0x00) /*!< BOOT0 pin disabled */  
#define OB_BOOT0_HW                   ((uint8_t)0x80) /*!< BOOT0 pin bonded with GPIO */
#define IS_OB_BOOT0SW(BOOT0) (((BOOT0) == OB_BOOT0_SW) || ((BOOT0) == OB_BOOT0_HW))

/**
  * @}
  */

/** @defgroup FLASH_Option_Bytes_VDDA_Analog_Monitoring
  * @{
  */

#define OB_VDDA_ANALOG_ON              ((uint8_t)0x20) /*!< Analog monitoring on VDDA Power source ON */
#define OB_VDDA_ANALOG_OFF             ((uint8_t)0x00) /*!< Analog monitoring on VDDA Power source OFF */

#define IS_OB_VDDA_ANALOG(ANALOG) (((ANALOG) == OB_VDDA_ANALOG_ON) || ((ANALOG) == OB_VDDA_ANALOG_OFF))

/**
  * @}
  */   

/** @defgroup FLASH_Option_Bytes_SRAM_Parity_Enable
  * @{
  */

#define OB_SRAM_PARITY_SET              ((uint8_t)0x00) /*!< SRAM parity enable Set */
#define OB_SRAM_PARITY_RESET            ((uint8_t)0x40) /*!< SRAM parity enable reset */

#define IS_OB_SRAM_PARITY(PARITY) (((PARITY) == OB_SRAM_PARITY_SET) || ((PARITY) == OB_SRAM_PARITY_RESET))

/**
  * @}
  */

/** @defgroup FLASH_Flags
  * @{
  */

#define FLASH_FLAG_BSY                 FLASH_SR_BSY     /*!< FLASH Busy flag */
#define FLASH_FLAG_PGERR               FLASH_SR_PGERR   /*!< FLASH Programming error flag */
#define FLASH_FLAG_WRPERR              FLASH_SR_WRPERR  /*!< FLASH Write protected error flag */
#define FLASH_FLAG_EOP                 FLASH_SR_EOP     /*!< FLASH End of Programming flag */

#define IS_FLASH_CLEAR_FLAG(FLAG) ((((FLAG) & (uint32_t)0xFFFFFFCB) == 0x00000000) && ((FLAG) != 0x00000000))

#define IS_FLASH_GET_FLAG(FLAG)  (((FLAG) == FLASH_FLAG_BSY) || ((FLAG) == FLASH_FLAG_PGERR) || \
                                  ((FLAG) == FLASH_FLAG_WRPERR) || ((FLAG) == FLASH_FLAG_EOP))

#ifdef __cplusplus
}
#endif

#endif

接着是IAR的工程项目


选择你要新建的工程的编程语言,有汇编,C,C++三种。






接着在工程选项中选择对应设备

接着按照普通KEIL工程文件夹格式建立文件


2.开发板特性的探究举例

STM32L053R8是基于ARM Cortex-M0+内核的超低功耗32位MCU,集成了多达64KB闪存,8KB SRAM,2KB EEPROM以及LCD,USB,ADC和DAC等性能,为0.95 DMIPS/MHz


我们一起学习一下开发板的AD,DA在MBED下的编程:

其中肉色的是ADC通道,而MBED的ADC编程也是非常简单,
#include "mbed.h"

AnalogIn analog_value(A0);
Serial pc(SERIAL_TX, SERIAL_RX);

int main() {
    while(1) {      
        uint16_t meas = analog_value.read_u16(); // Converts and read the analog input value
        pc.printf("%d\n",meas);
}

用起来非常简单,具体你想要那个AnalogIn ,就在声明时写哪个。
我链接的端口输出是这样的:



接着我们使用RTC来打印一下时间:首先来说一下基本概念

RTC由两个主要部分组成。第一部分(APB1接口)用来和 APB1总线相连。此单元还包含一组 16位寄存器,可通过 APB1总线对其进行读写操作。APB1接口以 APB1总线时钟为时钟,用来与 APB1总线接口。
另一部分(RTC核)由一系列可编程计数器组成,分成两个主要模块。第一个模块是 RTC的预分频模块,它可编程产生最长为 1秒的 RTC时间基准 TR_CLK。RTC的预分频模块包含了一个 20位的可编程分频器(RTC预分频器)。在每个TR_CLK周期中,如果在 RTC_CR 寄存器中设置了相应允许位,则 RTC产生一个中断(秒中断)。第 2个模块是一个 32位的可编程的计数器,它可被初始化为当前的系统时间。系统时间以 TR_CLK速度增长并与存储在 RTC_ALR寄存器中的可编程的时间相比较,如果 RTC_CR控制寄存器中设置了相应允许位,则比较匹配时将产生一个闹钟中断。
RTC初始化程序
void RTC_configuration()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP|RCC_APB1Periph_PWR,ENABLE);
PWR_BackupAccessCmd(ENABLE);//使能RTC后备寄存器的写
BKP_DeInit();//BKP寄存器全部设为缺省值
RCC_LSEConfig(RCC_LSE_ON);  //RCC打开了LSE时钟
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET);//等待LSE就绪,一般来说,如果谐振不对,就会死在这里,实际代码请慎重
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//RTC使用时钟源LSE
RCC_RTCCLKCmd(ENABLE);//RTC的时钟开启
RTC_WaitForSynchro();//RTC等待同步,
RTC_WaitForLastTask();//这个代码在RTC中常常出现,类似于等待就绪的含义
//RTC_ITConfig(RTC_IT_SEC, ENABLE);//RTC秒中断
RTC_WaitForLastTask();//
RTC_SetPrescaler(32767);//RTC预分频,32768HZ,分为一秒一个振荡,RTC period = RTCCLK/RTC_PR = (32.768KHz)/(32767+1)
RTC_WaitForLastTask(); //等待同步
PWR_BackupAccessCmd(DISABLE);//禁止RTC后备寄存器的写      
}
MBED的程序:
#include "mbed.h"
Serial pc(SERIAL_TX, SERIAL_RX);
DigitalOut myled(LED1);

int main() {
   
    pc.printf("RTC example\n");
    set_time(1387188323); // Set RTC time to 16 December 2013 10:05:23 UTC
    pc.printf("Date and time are set.\n");

    while(1) {

        time_t seconds = time(NULL);

        //printf("Time as seconds since January 1, 1970 = %d\n", seconds);
        
        pc.printf("Time as a basic string = %s", ctime(&seconds));

        //char buffer[32];
        //strftime(buffer, 32, "%I:%M:%S %p\n", localtime(&seconds));
        //printf("Time as a custom formatted string = %s", buffer);

        myled = !myled;      
        wait(1);
    }
}

接着我们来驱动一下ILI4系列的显示屏:

#include "mbed.h"

SPI device(SPI_MOSI, SPI_MISO, SPI_SCK);


其中SPI_MOSI对应你的开发板上面的默认的MOSI,MISO,SCK引脚

//这是我的板子上面的引脚分布图,SPI协议引脚都有在上面
typedef unsigned char uchar;
typedef unsigned int uint;
DigitalOut rs(D10);
//RS,是这种液晶屏幕的一个重要引脚,也常常标记为PC
DigitalOut cs(D9);
//CS与片选使能还是有一定区别
DigitalOut reset(D8);
//RESET复位引脚
uchar bitdata;
void  delay(uint t);

延时函数
void delay(uint time)
{
uint i,j;
  for(i=0;i<time;i++)
   for(j=0;j<2500;j++);
}
写命令
void  write_command(uchar c)
{
cs=0;
rs=0;
bitdata=c;
device.write(bitdata);
cs=1;      
}
写数据
void  write_data(uchar d)
{
cs=0;
rs=1;
bitdata=d;
device.write(bitdata);
cs=1;
}
写16位数据
void wr_com16(unsigned char i,unsigned char j)   
{         
  cs=0;
  rs=1;
  bitdata=i;
device.write(bitdata);
cs=1;  
  cs=0;
rs=1;
bitdata=j;
device.write(bitdata);
cs=1;

}
写命令与数据
void LCD_Write_COM_DATA(uchar i,uint j)   
{         
write_command(i);
wr_com16(j>>8,j);
}

初始化液晶屏幕
void lcd_initial()
{
   reset=0;
   delay(100);
   reset=1;
   delay(100);
    LCD_Write_COM_DATA(0x10, 0x0000); // Set SAP,DSTB,STB
    LCD_Write_COM_DATA(0x11, 0x0000); // Set APON,PON,AON,VCI1EN,VC
    LCD_Write_COM_DATA(0x12, 0x0000); // Set BT,DC1,DC2,DC3
    LCD_Write_COM_DATA(0x13, 0x0000); // Set GVDD
    LCD_Write_COM_DATA(0x14, 0x0000); // Set VCOMH/VCOML voltage
    delay(40); // Delay 20 ms

    // Please follow this power on sequence
    LCD_Write_COM_DATA(0x11, 0x0018); // Set APON,PON,AON,VCI1EN,VC
    LCD_Write_COM_DATA(0x12, 0x1121); // Set BT,DC1,DC2,DC3
    LCD_Write_COM_DATA(0x13, 0x0063); // Set GVDD
    LCD_Write_COM_DATA(0x14, 0x3961); // Set VCOMH/VCOML voltage
    LCD_Write_COM_DATA(0x10, 0x0800); // Set SAP,DSTB,STB
    delay(10); // Delay 10 ms
    LCD_Write_COM_DATA(0x11, 0x1038); // Set APON,PON,AON,VCI1EN,VC
    delay(30); // Delay 30 ms


    LCD_Write_COM_DATA(0x02, 0x0100); // set 1 line inversion


    //R01H:SM=0,GS=0,SS=1 (for details,See the datasheet of ILI9225)
    LCD_Write_COM_DATA(0x01, 0x011C); // set the display line number and display direction
    //R03H:BGR=1,ID0=1,ID1=1,AM=0 (for details,See the datasheet of ILI9225)
    LCD_Write_COM_DATA(0x03, 0x1030); // set GRAM write direction.


    LCD_Write_COM_DATA(0x07, 0x0000); // Display off
    LCD_Write_COM_DATA(0x08, 0x0808); // set the back porch and front porch
    LCD_Write_COM_DATA(0x0B, 0x1100); // set the clocks number per line
    LCD_Write_COM_DATA(0x0C, 0x0000); // CPU interface
    LCD_Write_COM_DATA(0x0F, 0x0501); // Set Osc
    LCD_Write_COM_DATA(0x15, 0x0020); // Set VCI recycling
    LCD_Write_COM_DATA(0x20, 0x0000); // RAM Address
    LCD_Write_COM_DATA(0x21, 0x0000); // RAM Address

    //------------------------ Set GRAM area --------------------------------//
    LCD_Write_COM_DATA(0x30, 0x0000);
    LCD_Write_COM_DATA(0x31, 0x00DB);
    LCD_Write_COM_DATA(0x32, 0x0000);
    LCD_Write_COM_DATA(0x33, 0x0000);
    LCD_Write_COM_DATA(0x34, 0x00DB);
    LCD_Write_COM_DATA(0x35, 0x0000);
    LCD_Write_COM_DATA(0x36, 0x00AF);
    LCD_Write_COM_DATA(0x37, 0x0000);
    LCD_Write_COM_DATA(0x38, 0x00DB);
    LCD_Write_COM_DATA(0x39, 0x0000);


    // ---------- Adjust the Gamma 2.2 Curve -------------------//
    LCD_Write_COM_DATA(0x50, 0x0603);
    LCD_Write_COM_DATA(0x51, 0x080D);
    LCD_Write_COM_DATA(0x52, 0x0D0C);
    LCD_Write_COM_DATA(0x53, 0x0205);
    LCD_Write_COM_DATA(0x54, 0x040A);
    LCD_Write_COM_DATA(0x55, 0x0703);
    LCD_Write_COM_DATA(0x56, 0x0300);
    LCD_Write_COM_DATA(0x57, 0x0400);
    LCD_Write_COM_DATA(0x58, 0x0B00);
    LCD_Write_COM_DATA(0x59, 0x0017);



    LCD_Write_COM_DATA(0x0F, 0x0701); // Vertical RAM Address Position
    LCD_Write_COM_DATA(0x07, 0x0012); // Vertical RAM Address Position
    delay(50); // Delay 50 ms
    LCD_Write_COM_DATA(0x07, 0x1017); // Vertical RAM Address Position  

}
设置显示位置的命令
void addset(unsigned int x,unsigned int y)
{
   LCD_Write_COM_DATA(0x20,x);
  //write_command(0x20);
   // LCD_Write_COM_DATA(0x36,x);
  //wr_com16(x>>8,x);
  LCD_Write_COM_DATA(0x21,y);
  //write_command(0x21);
   // LCD_Write_COM_DATA(0x36,x);
  //wr_com16(y>>8,y);
    write_command(0x22);
}
显示区域设置命令
void Lcd_SetRegion(uchar xStar, uchar yStar,uchar xEnd,uchar yEnd)
{

    LCD_Write_COM_DATA(0x36,xEnd);
    LCD_Write_COM_DATA(0x37,xStar);
    LCD_Write_COM_DATA(0x38,yEnd);
    LCD_Write_COM_DATA(0x39,yStar);
    LCD_Write_COM_DATA(0x20,xStar);
    LCD_Write_COM_DATA(0x21,yStar);

    write_command(0x22);   
}
屏幕清除命令
void Lcd_Clear(uchar DH,uchar DL)               
{   
   unsigned int i,m;
   Lcd_SetRegion(0,0,175,219);
   for(i=0;i<175;i++)
    for(m=0;m<219;m++)
    {   
        wr_com16(DH,DL);
    }   
}



int main() {
    lcd_initial();
   Lcd_Clear(0x07,0xe0);//绿色
/*RGB
#define RED          0xf800
#define GREEN        0x07e0
#define BLUE         0x001f
#define WHITE        0xffff
#define BLACK        0x0000
#define YELLOW  0xFFE0
#define GRAY0   0xEF7D           
#define GRAY1   0x8410              
#define GRAY2   0x4208              

*/
   while(1);
    {}
}

顺便写一个OLED的屏幕的测试程序,大家可以借鉴一下:

void OLED_Init(void)
{
    OLED_RST=0;
    DelayMs(50);
    OLED_RST=1;       //从上电到下面开始初始化要有足够的时间,即等待RC复位完毕   

    OLED_WrCmd(0xae);//--turn off oled panel
    OLED_WrCmd(0x00);//---set low column address
    OLED_WrCmd(0x10);//---set high column address
    OLED_WrCmd(0x40);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
    OLED_WrCmd(0x81);//--set contrast control register
    OLED_WrCmd(Brightness); // Set SEG Output Current Brightness
    OLED_WrCmd(0xa1);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
    OLED_WrCmd(0xc8);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
    OLED_WrCmd(0xa6);//--set normal display
    OLED_WrCmd(0xa8);//--set multiplex ratio(1 to 64)
    OLED_WrCmd(0x3f);//--1/64 duty
    OLED_WrCmd(0xd3);//-set display offset  Shift Mapping RAM Counter (0x00~0x3F)
    OLED_WrCmd(0x00);//-not offset
    OLED_WrCmd(0xd5);//--set display clock divide ratio/oscillator frequency
    OLED_WrCmd(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec
    OLED_WrCmd(0xd9);//--set pre-charge period
    OLED_WrCmd(0xf1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
    OLED_WrCmd(0xda);//--set com pins hardware configuration
    OLED_WrCmd(0x12);
    OLED_WrCmd(0xdb);//--set vcomh
    OLED_WrCmd(0x40);//Set VCOM Deselect Level
    OLED_WrCmd(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)
    OLED_WrCmd(0x02);//
    OLED_WrCmd(0x8d);//--set Charge Pump enable/disable
    OLED_WrCmd(0x14);//--set(0x10) disable
    OLED_WrCmd(0xa4);// Disable Entire Display On (0xa4/0xa5)
    OLED_WrCmd(0xa6);// Disable Inverse Display On (0xa6/a7)
    OLED_WrCmd(0xaf);//--turn on oled panel

    OLED_Fill(0x00);  //初始清屏
    OLED_SetPos(0,0);   
}

/*********************OLED写数据************************************/
void OLED_WrDat(unsigned char dat)
{
    unsigned char i;
    OLED_DC=1;  
    for(i=0;i<8;i++) //发送一个八位数据
    {
        if((dat << i) & 0x80)
        {
            OLED_SDA  = 1;
        }
        else  OLED_SDA  = 0;
        OLED_SCL = 0;
        OLED_SCL = 1;
    }
}

/*********************OLED写命令************************************/                                      
void OLED_WrCmd(unsigned char cmd)
{
    unsigned char i;
    OLED_DC=0;
    for(i=0;i<8;i++) //发送一个八位数据
    {
        if((cmd << i) & 0x80)
        {
            OLED_SDA  = 1;
        }
        else
        {
            OLED_SDA  = 0;
        }
        OLED_SCL = 0;
        OLED_SCL = 1;
    }
}


使用特权

评论回复
沙发
朝生| | 2022-12-9 14:11 | 只看该作者
L系列的和F系列的开发起来是一样的吧?

使用特权

评论回复
板凳
Henryko| | 2022-12-9 16:31 | 只看该作者
两个系列库函数略有区别,但是开发流程是一样的

使用特权

评论回复
地板
童雨竹| | 2024-11-1 08:18 | 只看该作者

电路的结构类似于全桥式,只是把其中的两只开关管(T3、T4)换成了两只等值大电容C1、C2。

使用特权

评论回复
5
Wordsworth| | 2024-11-1 09:21 | 只看该作者

通过对于PCB电路板边缘的孔或通孔做电镀石墨化

使用特权

评论回复
6
公羊子丹| | 2024-11-1 11:17 | 只看该作者

脉冲变压器磁能被积累的问题容易解决,

使用特权

评论回复
7
万图| | 2024-11-1 12:20 | 只看该作者

在PCB组装过程中通常使用两种类型的技术

使用特权

评论回复
8
Uriah| | 2024-11-1 13:23 | 只看该作者

一般PCB是V-CUT,

使用特权

评论回复
9
帛灿灿| | 2024-11-1 15:19 | 只看该作者

由于共模电流的同向性,会在线圈内产生同向的磁场而增大线圈的感抗

使用特权

评论回复
10
Bblythe| | 2024-11-1 16:22 | 只看该作者

在板的边缘上照常制作整个电镀通孔。

使用特权

评论回复
11
周半梅| | 2024-11-1 18:18 | 只看该作者

在交流电频率一定情况下,电感量越大,其对交流电阻碍能力越大

使用特权

评论回复
12
Pulitzer| | 2024-11-1 19:21 | 只看该作者

然后焊接到更大的PCB上

使用特权

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

本版积分规则

1324

主题

3809

帖子

0

粉丝