STM32_11(SPI)

SPI通信

  • SPI(Serial Peripheral Interface)是由Motorola公司开发的一种通用数据总线
  • 四根通信线:SCK(Serial Clock)、MOSI(Master Output Slave Input)、MISO(Master Input Slave Output)、SS(Slave Select)
  • MOSI:是主设备输出、从设备输入的数据信号线;、MISO:主设备输入、从设备输出的数据信号线; 
  • 同步,全双工
  • 支持总线挂载多设备(一主多从)

 

SPI硬件电路

  • 所有SPI设备的SCK、MOSI、MISO分别连在一起
  • 主机另外引出多条SS控制线,分别接到各从机的SS引脚
  • 输出引脚配置为推挽输出,输入引脚配置为浮空或上拉输入
  • 主机只能选择一个从机,选择多个从机就会导致数据冲突。当从机的SS引脚为高电平,就是从机未被选中,它的MISO引脚必须切换为高阻态,也就是把引脚断开。这样就可以防止一条线有多个输出,而导致的电平冲突问题。

 

移位示意图

移位寄存器有一个时钟输入端,因为SPI都是高位先行,所以每来一个时钟,移位寄存器就会向左移位,从机的移位寄存器同理。移位寄存器的时钟源是由主机提供的,这里叫做波特率发生器,它产生的时钟驱动主机的移位寄存器进行移位。同时,这个时钟也通过SCK引脚进行输出,接到从机的移位寄存器里。主机移位寄存器左边移出去的数据通过MOSI引脚,输入到从机的移位寄存器的右边,从机移位寄存器的数据根据MISO输入到主机移位寄存器的右边。

首先规定,波特率发生器时钟上升沿,所有移位寄存器向左移动一位,移出去的位放在引脚上,波特率发生器时钟的下降沿,引脚上的位,采样输入到移位寄存器的最低位。

 

SPI时序基本单元

起始条件和终止条件

  • 起始条件:SS从高电平切换到低电平
  • 终止条件:SS从低电平切换到高电平

 

模式0

  • 交换一个字节(模式0)
  • CPOL=0:空闲状态时,SCK为低电平
  • CPHA=0:SCK第一个边沿移入数据,第二个边沿移出数据

总体来说,MOSI和MISO都提前SCK半个周期。

 

模式1

  • 交换一个字节(模式1)
  • CPOL=0:空闲状态时,SCK为低电平
  • CPHA=1(时钟相位:决定第一个时钟采样移入还是第二个时钟采样移入):SCK第一个边沿移出数据,第二个边沿移入数据

SS高电平时,MISO用一条中间的线表示高阻态,SS下降沿之后,从机的MISO被允许开启输出。SS上升沿之后,从机的MISO必须置回高阻态。当SCK为上升沿时,主机和从机同时移除数据,主机通过MOSI移除最高位,此时的MOSI的电平就表示主机要发送数据B7,从机通过MISO移除最高位,此时MISO就表示从机要发送数据B7。之后时钟运行,产生下降沿,此时的主机和从机需同时移入数据,也就是数据采样,这里主机移除B7,进入从机移位寄存器的最低位,从机移除B7,进去主机移位寄存器的最低位。一个时钟脉冲产生完毕,一位数据传输完毕。

 

SPI时序(发送指令)

在这里我们使用的是模式0,首先SS是高电平,SCK是低电平。SS产生下降沿,时序开始,在下降沿时刻,MOSI和MISO就开始比变换数据,MOSI的指令码仍为0,所以保持低电平不变,MISO从机没有数据发给主机,引脚电平没有变换。从机采样输入,得到0,主机采样输入,得到1。之后主机要发送数据1,SCK下降沿,数据移出,主机将1移出到MOSI,MOSI变高电平。当主机发送0时候,SCK下降沿,MOSI变为0。SCK上升沿,数据采样,从机接收数据为0。总体来说,SCK低电平时变化时期,高电平时读取时期(下降沿变换数据,上升沿采样数据)。

这个SPI时序代表,主机用0x06换来了从机的0xFF。

 

SPI时序(指定地址写)

向SS指定的设备,发送写指令(0x02),随后在指定地址(Address[23:0])下,写入指定数据(Data)。

 

SPI时序(指定地址读)

向SS指定的设备,发送写指令(0x02),随后在指定地址(Address[23:0])下,写入指定数据(Data)。

 

SPI外设

  • STM32内部集成了硬件SPI收发电路,可以由硬件自动执行时钟生成、数据收发等功能,减轻CPU的负担
  • 可配置8位/16位数据帧、高位先行/低位先行
  • 时钟频率: fPCLK / (2, 4, 8, 16, 32, 64, 128, 256)
  • 支持多主机模型、主或从操作
  • 可精简为半双工/单工通信
  • 支持DMA
  • 兼容I2S协议
  • STM32F103C8T6 硬件SPI资源:SPI1、SPI2

 

SPI框图

首先,移位寄存器右边低位的数据一位一位地从MOSI移出,MISO的数据一位一位地以到做左边移位寄存器的数据高位。这个可以控制是低位先行还是高位先行。

假如我们需要连续发送一串数据,第一个数据写入发送缓冲区(TDR),当移位寄存器没有数据移位时,TDR的数据就会立刻转入移位寄存器,开始移位,这个转入时刻,会置状态寄存器的TXE为1(表示发送寄存器空),紧接着,下一个数据就可以提前写入TDR等待,一旦上个数据发送完成,下一个数据就可以立刻跟进,实现不间断的连续传输。当数据到移位寄存器后,它就会自动产生时钟,将数据移出去,在移除的过程中,MISO数据也会移入。一旦数据移除完成,数据移入也完成。这时,移入的数据就整体从移位寄存器转入到接收缓冲区RDR,这时会将状态寄存器RXNE置1(表示接收寄存器非空)。当我们检测RXNE置1后,就需要尽快把数据从RDR读出来,在下个数据来之前就可以读出RDR ,实现连续接收。

 

SPI基本结构

 

主模式全双工连续传输(效率更高)

 

非连续传输(代码友好)

步骤:

1、等待TXE置1;

2、写入数据到TDR寄存器;

3、等待RXNE为1;

4、读取RDR接收的数据。

 

W25Q64模块

  • W25Qxx系列是一种低成本、小型化、使用简单的非易失性存储器,常应用于数据存储、字库存储、固件程序存储等场景
  • 存储介质:Nor Flash(闪存)
  • 时钟频率:80MHz / 160MHz (Dual SPI) / 320MHz (Quad SPI)
  • 存储容量(24位地址):
    W25Q40:  4Mbit / 512KByte
    W25Q80:  8Mbit / 1MByte
    W25Q16:  16Mbit / 2MByte
    W25Q32:  32Mbit / 4MByte
    W25Q64:  64Mbit / 8MByte
    W25Q128:  128Mbit / 16MByte
    W25Q256:  256Mbit / 32MByte
 

W25Q64硬件电路

硬件原理图

/CS(/代表低电平有效或者CS上面有一横线也是低电平有效。

这里的CS对应SS,DI对应MOSI,DO对应MISO。

 

Flash操作注意事项

  • 写入操作时:
  • 写入操作前,必须先进行写使能
  • 每个数据位只能由1改写为0,不能由0改写为1
  • 写入数据前必须先擦除,擦除后,所有数据位变为1
  • 擦除必须按最小擦除单元进行(最小的擦除单元是一个扇区4096字节,最大的能把全部擦除)
  • 连续写入多字节时,最多写入一页(256字节)的数据,超过页尾位置的数据,会回到页首覆盖写入
  • 写入操作结束后,芯片进入忙状态,不响应新的读写操作
  • 读取操作时:直接调用读取时序,无需使能,无需额外操作,没有页的限制,读取操作结束后不会进入忙状态,但不能在忙状态时读取

 

代码部分

SPI软件配置代码

#include "Bsp_SPI.h"

/* SS写数据 */
void Bsp_SPI_W_SS(uint8_t BitValue)
{
    GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue);
}

/* SCK写数据 */
void Bsp_SPI_W_SCK(uint8_t BitValue)
{
    GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)BitValue);
}

/* MOSI写数据 */
void Bsp_SPI_W_MOSI(uint8_t BitValue)
{
    GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)BitValue);
}

/* MISO读数据 */
uint8_t Bsp_SPI_R_MISO(void)
{
    return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6);
}

/* SPI初始化 */
void Bsp_SPI_Init(void)
{
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    Bsp_SPI_W_SS(1);
    Bsp_SPI_W_SCK(0);

}

/* SPI起始 */
void Bsp_SPI_Start(void)
{
    Bsp_SPI_W_SS(0);
}

/* SPI终止 */
void Bsp_SPI_Stop(void)
{
    Bsp_SPI_W_SS(1);
}

/* MOSI和MISO交换字节 */
/* 模式0 */
uint8_t Bsp_SPI_SwapByte(uint8_t ByteSend)
{
    uint8_t ByteReceive = 0x00;

    for (uint8_t i = 0; i < 8; i++)
    {
        Bsp_SPI_W_MOSI(ByteSend & (0x80 >> i));
        Bsp_SPI_W_SCK(1);
        if (Bsp_SPI_R_MISO() == 1)
        {
            ByteReceive |= (0x80 >> i);
        }
        Bsp_SPI_W_SCK(0);
    }

    return ByteReceive;
}

/* 模式1 */
/*uint8_t Bsp_SPI_SwapByte(uint8_t ByteSend)
{
    uint8_t ByteReceive = 0x00;

    for (uint8_t i = 0; i < 8; i++)
    {
        Bsp_SPI_W_SCK(1);
        Bsp_SPI_W_MOSI(ByteSend &(0x80 >> i));
        Bsp_SPI_W_SCK(0);
        if (Bsp_SPI_R_MISO == 1)
        {
            ByteReceive |= (0x80 >> i);
        }
    }

    return ByteReceive;
}*/

/* 模式3 */
/*uint8_t Bsp_SPI_SwapByte(uint8_t ByteSend)
{
    uint8_t ByteReceive = 0x00;

    for (uint8_t i = 0; i < 8; i++)
    {
        Bsp_SPI_W_SCK(0);
        Bsp_SPI_W_MOSI(ByteSend &(0x80 >> i));
        Bsp_SPI_W_SCK(1);
        if (Bsp_SPI_R_MISO == 1)
        {
            ByteReceive |= (0x80 >> i);
        }
    }

    return ByteReceive;
}*/

/* 模式2 */
/*uint8_t Bsp_SPI_SwapByte(uint8_t ByteSend)
{
    uint8_t ByteReceive = 0x00;

    for (uint8_t i = 0; i < 8; i++)
    {
        Bsp_SPI_W_MOSI(ByteSend &(0x80 >> i));
        Bsp_SPI_W_SCK(0);
        if (Bsp_SPI_R_MISO == 1)
        {
            ByteReceive |= (0x80 >> i);
        }
        Bsp_SPI_W_SCK(1);
    }

    return ByteReceive;
}*/

 

W25Q64地址封装

#ifndef __W25Q64_INS_H
#define __W25Q64_INS_H

#define W25Q64_WRITE_ENABLE                         0x06
#define W25Q64_WRITE_DISABLE                        0x04
#define W25Q64_READ_STATUS_REGISTER_1               0x05
#define W25Q64_READ_STATUS_REGISTER_2               0x35
#define W25Q64_WRITE_STATUS_REGISTER                0x01
#define W25Q64_PAGE_PROGRAM                         0x02
#define W25Q64_QUAD_PAGE_PROGRAM                    0x32
#define W25Q64_BLOCK_ERASE_64KB                     0xD8
#define W25Q64_BLOCK_ERASE_32KB                     0x52
#define W25Q64_SECTOR_ERASE_4KB                     0x20
#define W25Q64_CHIP_ERASE                           0xC7
#define W25Q64_ERASE_SUSPEND                        0x75
#define W25Q64_ERASE_RESUME                         0x7A
#define W25Q64_POWER_DOWN                           0xB9
#define W25Q64_HIGH_PERFORMANCE_MODE                0xA3
#define W25Q64_CONTINUOUS_READ_MODE_RESET           0xFF
#define W25Q64_RELEASE_POWER_DOWN_HPM_DEVICE_ID     0xAB
#define W25Q64_MANUFACTURER_DEVICE_ID               0x90
#define W25Q64_READ_UNIQUE_ID                       0x4B
#define W25Q64_JEDEC_ID                             0x9F
#define W25Q64_READ_DATA                            0x03
#define W25Q64_FAST_READ                            0x0B
#define W25Q64_FAST_READ_DUAL_OUTPUT                0x3B
#define W25Q64_FAST_READ_DUAL_IO                    0xBB
#define W25Q64_FAST_READ_QUAD_OUTPUT                0x6B
#define W25Q64_FAST_READ_QUAD_IO                    0xEB
#define W25Q64_OCTAL_WORD_READ_QUAD_IO              0xE3

#define W25Q64_DUMMY_BYTE                           0xFF                // 空地址,代表没用的地址,因为在传输过程中总会只有发送或只有接收的时候

#endif

 

软件SPI读取W25Q64

#include "Bsp_W25Q64.h"

void W25Q64_Init(void)
{
    Bsp_SPI_Init();
}

/* 读取ID */
void W25Q64_ReadID(uint8_t *MID, uint16_t *DID)
{
    Bsp_SPI_Start();
    Bsp_SPI_SwapByte(W25Q64_JEDEC_ID);               // 发送0x9F指令码
    *MID = Bsp_SPI_SwapByte(W25Q64_DUMMY_BYTE);      // 返回制造厂商ID
    *DID = Bsp_SPI_SwapByte(W25Q64_DUMMY_BYTE);      // 返回设备ID的高8位
    *DID <<= 8;                         
    *DID |= Bsp_SPI_SwapByte(W25Q64_DUMMY_BYTE);     // 返回设备ID的低8位
    Bsp_SPI_Stop();
}

/* 使能 */
void W25Q64_WriteEnable(void)
{
    Bsp_SPI_Start();
    Bsp_SPI_SwapByte(W25Q64_WRITE_ENABLE);         
    Bsp_SPI_Stop();
}

/* 读状态寄存器1(主要读取BUSY位,判断是否在忙) */
void W25Q64_WaitBusy(void)
{
    uint32_t TimeOut = 100000;

    Bsp_SPI_Start();
    Bsp_SPI_SwapByte(W25Q64_READ_STATUS_REGISTER_1);   
    while ((Bsp_SPI_SwapByte(W25Q64_DUMMY_BYTE) & 0x01) == 0x01)        // 判断状态寄存器1的最低位,也就是BUSY位是否在忙。0:忙     1:在忙
    {
        TimeOut--;
        if (TimeOut == 0)
        {
            break;
        }
    }
    Bsp_SPI_Stop();
}

/* 页编程 */
void W25Q64_PageProgram(uint32_t Address, uint8_t *DataAarry, uint16_t Length)
{
    W25Q64_WriteEnable();                       // 使能
    Bsp_SPI_Start();
    Bsp_SPI_SwapByte(W25Q64_PAGE_PROGRAM);
    Bsp_SPI_SwapByte(Address >> 16);
    Bsp_SPI_SwapByte(Address >> 8);
    Bsp_SPI_SwapByte(Address);

    for (uint16_t i = 0; i < Length; i++)
    {
        Bsp_SPI_SwapByte(DataAarry[i]);
    }
    Bsp_SPI_Stop();

    W25Q64_WaitBusy();
}

/* 扇区擦除 */
void W25Q64_SectorErase(uint32_t Address)
{
    W25Q64_WriteEnable();                       // 使能
    Bsp_SPI_Start();
    Bsp_SPI_SwapByte(W25Q64_SECTOR_ERASE_4KB);
    Bsp_SPI_SwapByte(Address >> 16);
    Bsp_SPI_SwapByte(Address >> 8);
    Bsp_SPI_SwapByte(Address);
    Bsp_SPI_Stop();

    W25Q64_WaitBusy();
}

/* 读数据 */
void W25Q64_ReadData(uint32_t Address, uint8_t *DataAarry, uint32_t Length)
{
    Bsp_SPI_Start();
    Bsp_SPI_SwapByte(W25Q64_READ_DATA);
    Bsp_SPI_SwapByte(Address >> 16);
    Bsp_SPI_SwapByte(Address >> 8);
    Bsp_SPI_SwapByte(Address);

    for (uint32_t i = 0; i < Length; i++)
    {
        DataAarry[i] = Bsp_SPI_SwapByte(W25Q64_DUMMY_BYTE);
    }
    Bsp_SPI_Stop();
}

 

硬件SPI读取W25Q64

#include "Bsp_SPI.h"

/* SS写数据 */
void Bsp_SPI_W_SS(uint8_t BitValue)
{
    GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue);
}

/* SPI初始化 */
void Bsp_SPI_Init(void)
{
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    SPI_InitTypeDef SPI_InitStructure;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;                    // 分频系数,分频越高速度越快(注意:SPI1是72M,SPI2是36M。因为SPI1是在APB2,SPI2是在APB1)
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                                            // 选择第一个边沿采样还是第二个边沿采样
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                                              // 时钟极性:因为在这里选择模式0
    SPI_InitStructure.SPI_CRCPolynomial = 7;                                                // CRC校验多项式,默认值7
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                                       // 8位数据帧
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;                      // 双线全双工模式
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                                      // 高位先行
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                                           // 选择向前设备时SPI主机
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                                               // NSS引脚,一般没用到选择软件NSS
    SPI_Init(SPI1, &SPI_InitStructure);

    SPI_Cmd(SPI1, ENABLE);

    Bsp_SPI_W_SS(1);

}

/* SPI起始 */
void Bsp_SPI_Start(void)
{
    Bsp_SPI_W_SS(0);
}

/* SPI终止 */
void Bsp_SPI_Stop(void)
{
    Bsp_SPI_W_SS(1);
}

/* MOSI和MISO交换字节 */
/* 模式0 */
uint8_t Bsp_SPI_SwapByte(uint8_t ByteSend)
{
    uint32_t TimeOut = 10000;
    uint8_t ByteReceive;
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != 1)
    {
        TimeOut--;
        if (TimeOut == 0)
        {
            break;
        } 
    }
    SPI_I2S_SendData(SPI1, ByteSend);
    TimeOut = 10000;
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) != 1)
    {
        TimeOut--;
        if (TimeOut == 0)
        {
            break;
        } 
    }
    ByteReceive = SPI_I2S_ReceiveData(SPI1);
    return  ByteReceive;
}

 

主程序 

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Bsp_W25Q64.h"

uint8_t MID;
uint16_t DID;
uint8_t ArrayWrite[] = {0x11, 0x22, 0x33, 0x44};
uint8_t ArrayRead[4];

int main(void)
{

    OLED_Init();                        
    W25Q64_Init();

    /* 显示厂商和设备ID号 */
    OLED_ShowString(1, 1, "MID:    DID:");
    OLED_ShowString(2, 1, "W:");
    OLED_ShowString(3, 1, "R:");

    W25Q64_ReadID(&MID, &DID);
    OLED_ShowHexNum(1, 5, MID, 2);
    OLED_ShowHexNum(1, 13, DID, 4);

    W25Q64_SectorErase(0x000000);                    // 只要末尾3个十六进制数为0,那肯定是扇区的起始地址(不擦除,掉电不丢失)。如果不擦除则改写则会数据出错,因为只能1变0不能0变1的操作所以修改数据前得擦除。
    W25Q64_PageProgram(0x00000, ArrayWrite, 4);      // 写入数据ArrayWrite,并且写入的数据不能跨页

    W25Q64_ReadData(0x000000, ArrayRead, 4);         // 读数据

    /* 显示写入数据 */
    OLED_ShowHexNum(2, 3, ArrayWrite[0], 2);
    OLED_ShowHexNum(2, 6, ArrayWrite[1], 2);
    OLED_ShowHexNum(2, 9, ArrayWrite[2], 2);
    OLED_ShowHexNum(2, 12, ArrayWrite[3], 2);

    /* 显示读出数据 */
    OLED_ShowHexNum(3, 3, ArrayRead[0], 2);
    OLED_ShowHexNum(3, 6, ArrayRead[1], 2);
    OLED_ShowHexNum(3, 9, ArrayRead[2], 2);
    OLED_ShowHexNum(3, 12, ArrayRead[3], 2);

    while (1)
    {
        
    }
}

 

本文作者:每天学习之路

本文链接:https://www.cnblogs.com/toutiegongzhu/p/17418651.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   烟儿公主  阅读(173)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 夏日大冒险 暴躁的兔子
夏日大冒险 - 暴躁的兔子
00:00 / 00:00
An audio error has occurred.

作词 : 暴躁的兔子

作曲 : 暴躁的兔子

编曲 : IOF

混音:Gfanfan

出品:网易飓风

夏天 不要再浪费时间

实现 你承诺过的改变

别再 找一堆借口拖延

现在就和我一起飞向海边

人生苦短 你应该学会如何作乐

低着头还怎么应对挫折

人应该为自己活着

不用去迎合

要去寻欢作乐

撮合我的浪漫和悲欢

把这荒诞人生都塞满

生活难免磕磕绊绊

对抗生活的平庸就是浪漫

学会取悦自己逆风翻盘

去反抗变态的三观

把条条框框都砸烂

建立新的规则推翻谈判

无可救药的人呐

和我一起去海边

看那日出和晚霞 海天一线

看阳光穿越地平线

现实交织的明天

就在这个夏天

为自己改变

别怕山高路远

去冒险

我真的不care你是否会喜欢我

不跟风被定义的美 全都是灾祸

我才不讨好大多数绝不与示弱

过好你的生活

你管我应该怎么快活

没有人能有资格审判

别人的生活和牵绊

快闭上你的高谈阔论

乘风破浪吧 理想的风帆

我就是肆意张扬又如何

我就是锋芒毕露又如何

我就是离经叛道又如何

我就是要出格 你管我要如何

我就是与众不同又如何

我就是特立独行又如何

我就是不知好歹又如何

你管我怎样出格 你管我如何

无可救药的人呐

和我一起去海边

看那日出和晚霞 海天一线

看阳光穿越地平线

现实交织的明天

就在这个夏天

为自己改变

别怕山高路远

不知进退的人呐

和我一起去海边

聊聊曾经的理想 一起想当年

那曾想改变世界的人

是否还满腔热忱

不羁的我们放肆着

反抗那命运的指针

解放灵魂

推广:网易飓风

企划:贾焱祺

监制:徐思灵

出品人:谢奇笛