MSP430学习笔记(四)丨I2C通信(MSP430F5529驱动OLED显示屏)

这篇具有很好参考价值的文章主要介绍了MSP430学习笔记(四)丨I2C通信(MSP430F5529驱动OLED显示屏)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

​  笔者学习采用单片机型号为MSP430F5529,使用MSP-EXP430F5529LP开发板。
​  笔者拥有一定的STM32基础,在学习MSP430的过程中,最开始苦于没有合适的OLED显示驱动代码,所以花了很多时间钻研。综合网上的各种代码,笔者认为江协科技的STM32课程中提供的OLED代码使用方便,代码逻辑清晰便于学习和使用,所以花了很多时间来研究那一版的代码写法和MSP430的I2C通信。本篇文章主要实现MSP430的基于硬件I2C的主模式信息传输。


一、USCI_B——I2C主模式操作

1.1 函数调用顺序说明

​  为了驱动主控模块,需要按照以下顺序调用API:

  1. USCI_B_I2C_initMaster() - 初始化USCI_B_I2C主控模块。
  2. USCI_B_I2C_setSlaveAddress() - 设置主控将与之通信的从设备地址。这里的从设备地址是不加读写操作位的从设备地址。MSP430的库函数会在时序开头的起始条件后根据传输/接收模式自动拼接设备地址+读写位的第一个字节。
  3. USCI_B_I2C_setMode() - 选择操作模式(发送或接收)。
  4. USCI_B_I2C_enable() - 启用USCI_B_I2C模块。
  5. USCI_B_I2C_enableInterrupt()(如果使用中断) - 启用USCI_B_I2C中断。如果需要传输数据,则需要使能传输中断;如果需要接收数据,则需要使能接收中断。

​  接下来可以根据需要调用传输或接收相关的API。

​  用户首先需要调用USCI_B_I2C_initMaster()来初始化USCI_B_I2C模块并将其配置为主控。该函数将设置时钟和数据速率。然后使用USCI_B_I2C_setSlaveAddress来设置主控与之通信的从设备地址。接下来使用USCI_B_I2C_setMode选择操作模式(发送或接收)。现在可以使用USCI_B_I2C_enable启用USCI_B_I2C模块。建议在启用中断之前启用USCI_B_I2C模块。在启用中断(如果有)后,此时可以发起任何数据的发送或接收。

​  可以通过调用以下列出的相关API来在总线上发起传输。如果设备处于等待IFG标志设置的状态中,可以使用包含超时的API,以避免陷入无限循环。

1.2 不同情况下的函数调用顺序

​  主控单字节发送:

  • USCI_B_I2C_masterSendSingleByte()

​  主控多字节发送(之后的三个函数需要在中断中调用):

  • USCI_B_I2C_masterSendMultiByteStart()
  • USCI_B_I2C_masterSendMultiByteNext()
  • USCI_B_I2C_masterSendMultiByteFinish()
  • USCI_B_I2C_masterSendMultiByteStop()

​  主控单字节接收:

  • USCI_B_I2C_masterReceiveSingleStart()
  • USCI_B_I2C_masterReceiveSingle()

​  主控多字节接收(之后的三个函数需要在中断中调用):

  • USCI_B_I2C_masterReceiveMultiByteStart()
  • USCI_B_I2C_masterReceiveMultiByteNext()
  • USCI_B_I2C_masterReceiveMultiByteFinish()
  • USCI_B_I2C_masterReceiveMultiByteStop()

​  带超时的主控单字节发送:

  • USCI_B_I2C_masterSendSingleByteWithTimeout()

​  带超时的主控多字节发送:

  • USCI_B_I2C_masterSendMultiByteStartWithTimeout()
  • USCI_B_I2C_masterSendMultiByteNextWithTimeout()
  • USCI_B_I2C_masterReceiveMultiByteFinishWithTimeout()
  • USCI_B_I2C_masterSendMultiByteStopWithTimeout()

​  带超时的主控单字节接收:

  • USCI_B_I2C_masterReceiveSingleStartWithTimeout()

​  对于基于中断的传输,用户必须为USCI_B_I2C设备注册中断处理程序并启用USCI_B_I2C中断。

  在MSP430中,超时(Timeout)是指在特定时间内未能完成某个操作或接收到预期的响应。它通常用于处理通信协议中的错误或异常情况,以防止程序陷入无限等待或死锁状态。
  在某些通信协议中,例如I2C或UART,设备之间的通信可能会发生错误或超时。当发生这种情况时,为了确保程序的正常运行,可以设置一个超时机制。超时机制会在设定的时间内检测是否收到预期的响应,如果超过设定的时间仍未收到响应,则认为操作失败或通信出现问题。
  超时可以根据具体应用和通信协议的要求进行设置。通常,可以使用定时器或计数器来实现超时功能。在超时期间,程序可以执行相应的错误处理或尝试重新发送数据。
  超时的设定取决于通信环境、通信速度和所需的响应时间。通过合理设置超时时间,可以提高系统的鲁棒性和可靠性,避免长时间的等待或阻塞情况,从而提高程序的性能和响应能力。

二、I2C通信库函数

// 初始化I2C主模块
void USCI_B_I2C_initMaster(uint16_t baseAddress, USCI_B_I2C_initMasterParam *param);

// 初始化I2C从模块
void USCI_B_I2C_initSlave(uint16_t baseAddress, uint8_t slaveAddress);

// 启用I2C模块
void USCI_B_I2C_enable(uint16_t baseAddress);

// 禁用I2C模块
void USCI_B_I2C_disable(uint16_t baseAddress);

// 设置I2C主模块将在总线上放置的地址
void USCI_B_I2C_setSlaveAddress(uint16_t baseAddress, uint8_t slaveAddress);

// 设置I2C设备的模式
void USCI_B_I2C_setMode(uint16_t baseAddress, uint8_t mode);

// 从I2C模块发送一个字节
void USCI_B_I2C_slavePutData(uint16_t baseAddress, uint8_t transmitData);

// 接收已发送到I2C模块的字节
uint8_t USCI_B_I2C_slaveGetData(uint16_t baseAddress);

// 指示I2C总线是否忙
uint8_t USCI_B_I2C_isBusBusy(uint16_t baseAddress);

// 【已弃用】该功能可能在将来的版本中被删除。指示I2C模块是否忙
uint8_t USCI_B_I2C_isBusy(uint16_t baseAddress);

// 指示是否已发送停止位
uint8_t USCI_B_I2C_masterIsStopSent(uint16_t baseAddress);

// 指示是否已发送起始位
uint8_t USCI_B_I2C_masterIsStartSent(uint16_t baseAddress);

// 主模块用于启动起始位的函数
void USCI_B_I2C_masterSendStart(uint16_t baseAddress);

// 启用单独的I2C中断源
void USCI_B_I2C_enableInterrupt(uint16_t baseAddress, uint8_t mask);

// 禁用单独的I2C中断源
void USCI_B_I2C_disableInterrupt(uint16_t baseAddress, uint8_t mask);

// 清除I2C中断源
void USCI_B_I2C_clearInterrupt(uint16_t baseAddress, uint8_t mask);

// 获取当前I2C中断状态
uint8_t USCI_B_I2C_getInterruptStatus(uint16_t baseAddress, uint8_t mask);

// 从主模块向从模块发送单个字节
void USCI_B_I2C_masterSendSingleByte(uint16_t baseAddress, uint8_t txData);

// 从主模块向从模块发送单个字节,并带有超时功能
bool USCI_B_I2C_masterSendSingleByteWithTimeout(uint16_t baseAddress, uint8_t txData, uint32_t timeout);

// 从主模块启动多字节传输到从模块
void USCI_B_I2C_masterSendMultiByteStart(uint16_t baseAddress, uint8_t txData);

// 从主模块启动多字节传输到从模块,并带有超时功能
bool USCI_B_I2C_masterSendMultiByteStartWithTimeout(uint16_t baseAddress, uint8_t txData, uint32_t timeout);

// 从主模块继续多字节传输到从模块
void USCI_B_I2C_masterSendMultiByteNext(uint16_t baseAddress, uint8_t txData);

// 从主模块继续多字节传输到从模块,并带有超时功能
bool USCI_B_I2C_masterSendMultiByteNextWithTimeout(uint16_t baseAddress, uint8_t txData, uint32_t timeout);

// 从主模块完成多字节传输到从模块
void USCI_B_I2C_masterSendMultiByteFinish(uint16_t baseAddress, uint8_t txData);

// 从主模块完成多字节传输到从模块,并带有超时功能
bool USCI_B_I2C_masterSendMultiByteFinishWithTimeout(uint16_t baseAddress, uint8_t txData, uint32_t timeout);

// 从主模块发送停止位以结束多字节传输到从模块
void USCI_B_I2C_masterSendMultiByteStop(uint16_t baseAddress);

// 从主模块发送停止位以结束多字节传输到从模块,并带有超时功能
bool USCI_B_I2C_masterSendMultiByteStopWithTimeout(uint16_t baseAddress, uint32_t timeout);

// 从主模块开始多字节接收
void USCI_B_I2C_masterReceiveMultiByteStart(uint16_t baseAddress);

// 从主模块逐个字节开始多字节接收
uint8_t USCI_B_I2C_masterReceiveMultiByteNext(uint16_t baseAddress);

// 从主模块完成多字节接收
uint8_t USCI_B_I2C_masterReceiveMultiByteFinish(uint16_t baseAddress);

// 从主模块完成多字节接收,并带有超时功能
bool USCI_B_I2C_masterReceiveMultiByteFinishWithTimeout(uint16_t baseAddress, uint8_t *rxData, uint32_t timeout);

// 从主模块发送停止位以结束多字节接收
void USCI_B_I2C_masterReceiveMultiByteStop(uint16_t baseAddress);

// 从主模块开始单字节接收
void USCI_B_I2C_masterReceiveSingleStart(uint16_t baseAddress);

// 从主模块开始单字节接收,并带有超时功能
bool USCI_B_I2C_masterReceiveSingleStartWithTimeout(uint16_t baseAddress, uint32_t timeout);

// 从I2C主模块接收已发送到其的字节
uint8_t USCI_B_I2C_masterReceiveSingle(uint16_t baseAddress);

// 返回用于DMA模块的I2C接收缓冲区的地址
uint32_t USCI_B_I2C_getReceiveBufferAddressForDMA(uint16_t baseAddress);

// 返回用于DMA模块的I2C发送缓冲区的地址
uint32_t USCI_B_I2C_getTransmitBufferAddressForDMA(uint16_t baseAddress);

三、OLED驱动代码

  • OLED.h
/*
 * OLED.h
 *
 *  Created on: 2023年7月12日
 *      Author: Include everything
 */

#ifndef HARDWARE_OLED_H_
#define HARDWARE_OLED_H_

void OLED_Init(void);
void OLED_Clear(void);
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char);
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String);
void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length);
void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);

#endif /* HARDWARE_OLED_H_ */

  • OLED_Font.h
/*
 * OLED_Font.h
 *
 *  Created on: 2023年7月12日
 *      Author: Include everything
 */

#ifndef HARDWARE_OLED_FONT_H_
#define HARDWARE_OLED_FONT_H_

/*OLED字模库,宽8像素,高16像素*/
const uint8_t OLED_F8x16[][16]=
{
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//  0

    0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 1

    0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 2

    0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,
    0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 3

    0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,
    0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 4

    0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,
    0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 5

    0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,
    0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 6

    0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 7

    0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,
    0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 8

    0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,
    0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 9

    0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,
    0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 10

    0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,
    0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 11

    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 12

    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 13

    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 14

    0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,
    0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 15

    0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,
    0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 16

    0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,
    0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 17

    0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,
    0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 18

    0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,
    0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 19

    0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,
    0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 20

    0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,
    0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 21

    0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,
    0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 22

    0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,
    0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 23

    0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,
    0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 24

    0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,
    0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 25

    0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,
    0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 26

    0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,
    0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 27

    0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,
    0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 28

    0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,
    0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 29

    0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,
    0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 30

    0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,
    0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 31

    0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,
    0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 32

    0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,
    0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 33

    0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,
    0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 34

    0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,
    0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 35

    0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,
    0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 36

    0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,
    0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 37

    0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,
    0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 38

    0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,
    0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 39

    0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,
    0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 40

    0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,
    0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 41

    0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,
    0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 42

    0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,
    0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 43

    0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,
    0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 44

    0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,
    0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 45

    0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,
    0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 46

    0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,
    0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 47

    0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,
    0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 48

    0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,
    0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 49

    0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,
    0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 50

    0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,
    0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 51

    0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,
    0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 52

    0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,
    0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 53

    0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,
    0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 54

    0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,
    0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 55

    0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,
    0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 56

    0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,
    0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 57

    0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,
    0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 58

    0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,
    0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 59

    0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 60

    0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,
    0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 61

    0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 62

    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 63

    0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 64

    0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,
    0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 65

    0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,
    0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 66

    0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,
    0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 67

    0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,
    0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 68

    0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,
    0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 69

    0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,
    0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 70

    0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,
    0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 71

    0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,
    0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 72

    0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,
    0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 73

    0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,
    0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 74

    0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,
    0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 75

    0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,
    0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 76

    0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,
    0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 77

    0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,
    0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 78

    0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,
    0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 79

    0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,
    0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 80

    0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,
    0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 81

    0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,
    0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 82

    0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,
    0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 83

    0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,
    0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 84

    0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,
    0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 85

    0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,
    0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 86

    0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,
    0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 87

    0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,
    0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 88

    0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,
    0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 89

    0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,
    0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 90

    0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,
    0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 91

    0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 92

    0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,
    0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 93

    0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~ 94
};

#endif /* HARDWARE_OLED_FONT_H_ */

  • OLED.c
/*
 * OLED.c
 *
 *  Created on: 2023年7月12日
 *      Author: Include everything
 */

#include <driverlib.h>
#include "OLED_Font.h"

//#define     I2C_USCI_IV         UCB0IV

static uint8_t LastByteFlag = 0;
static uint8_t I2C_Tx_BufData = 0;      // 数据缓冲字节,供中断函数使用

/*引脚初始化*/
void OLED_I2C_Init(void)
{
    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P3, GPIO_PIN0 | GPIO_PIN1);

    USCI_B_I2C_initMasterParam USCI_B_I2C_InitStructure;

    USCI_B_I2C_InitStructure.dataRate = USCI_B_I2C_SET_DATA_RATE_400KBPS;
    USCI_B_I2C_InitStructure.i2cClk = UCS_getSMCLK();
    USCI_B_I2C_InitStructure.selectClockSource = USCI_B_I2C_CLOCKSOURCE_SMCLK;

    USCI_B_I2C_initMaster(USCI_B0_BASE, &USCI_B_I2C_InitStructure);

    // 设置从机地址,之后的时序中不需要再发送从机地址
    USCI_B_I2C_setSlaveAddress(USCI_B0_BASE, 0x78 >> 1);

    USCI_B_I2C_setMode(USCI_B0_BASE, USCI_B_I2C_TRANSMIT_MODE);
    USCI_B_I2C_enable(USCI_B0_BASE);

    // 使能传送中断,用来接收从机的响应信号
    USCI_B_I2C_clearInterrupt(USCI_B0_BASE, USCI_B_I2C_TRANSMIT_INTERRUPT);
    USCI_B_I2C_enableInterrupt(USCI_B0_BASE, USCI_B_I2C_TRANSMIT_INTERRUPT);
}

/**
  * @brief  I2C发送一个字节
  * @param  Byte 要发送的一个字节
  * @retval 无
  */
void OLED_I2C_SendByte(uint8_t Byte)
{
    while (USCI_B_I2C_isBusBusy(USCI_B0_BASE));

    USCI_B_I2C_masterSendSingleByte(USCI_B0_BASE, Byte);

    // 等待中断响应
    __bis_SR_register(GIE + LPM0_bits);
    __no_operation();
}

/**
  * @brief  OLED写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void OLED_WriteCommand(uint8_t Command)
{
    while (USCI_B_I2C_isBusBusy(USCI_B0_BASE));

    LastByteFlag = 0;
    I2C_Tx_BufData = Command;
    USCI_B_I2C_masterSendMultiByteStart(USCI_B0_BASE, 0x00);

    // 等待中断响应
    __bis_SR_register(GIE + LPM0_bits);
    __no_operation();
}

/**
  * @brief  OLED写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void OLED_WriteData(uint8_t Data)
{
    while (USCI_B_I2C_isBusBusy(USCI_B0_BASE));

    LastByteFlag = 0;
    I2C_Tx_BufData = Data;
    USCI_B_I2C_masterSendMultiByteStart(USCI_B0_BASE, 0x40);

    // 等待中断响应
    __bis_SR_register(GIE + LPM0_bits);
    __no_operation();
}

/**
  * @brief  OLED设置光标位置
  * @param  Y 以左上角为原点,向下方向的坐标,范围:0~7
  * @param  X 以左上角为原点,向右方向的坐标,范围:0~127
  * @retval 无
  */
void OLED_SetCursor(uint8_t Y, uint8_t X)
{
    OLED_WriteCommand(0xB0 | Y);                    //设置Y位置
    OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4));    //设置X位置高4位
    OLED_WriteCommand(0x00 | (X & 0x0F));           //设置X位置低4位
}

/**
  * @brief  OLED清屏
  * @param  无
  * @retval 无
  */
void OLED_Clear(void)
{
    uint8_t i, j;
    for (j = 0; j < 8; j++)
    {
        OLED_SetCursor(j, 0);
        for(i = 0; i < 128; i++)
        {
            OLED_WriteData(0x00);
        }
    }
}

/**
  * @brief  OLED显示一个字符
  * @param  Line 行位置,范围:1~4
  * @param  Column 列位置,范围:1~16
  * @param  Char 要显示的一个字符,范围:ASCII可见字符
  * @retval 无
  */
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char)
{
    uint8_t i;
    OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8);       //设置光标位置在上半部分
    for (i = 0; i < 8; i++)
    {
        OLED_WriteData(OLED_F8x16[Char - ' '][i]);          //显示上半部分内容
    }
    OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8);   //设置光标位置在下半部分
    for (i = 0; i < 8; i++)
    {
        OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]);      //显示下半部分内容
    }
}

/**
  * @brief  OLED显示字符串
  * @param  Line 起始行位置,范围:1~4
  * @param  Column 起始列位置,范围:1~16
  * @param  String 要显示的字符串,范围:ASCII可见字符
  * @retval 无
  */
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String)
{
    uint8_t i;
    for (i = 0; String[i] != '\0'; i++)
    {
        OLED_ShowChar(Line, Column + i, String[i]);
    }
}

/**
  * @brief  OLED次方函数
  * @retval 返回值等于X的Y次方
  */
uint32_t OLED_Pow(uint32_t X, uint32_t Y)
{
    uint32_t Result = 1;
    while (Y--)
    {
        Result *= X;
    }
    return Result;
}

/**
  * @brief  OLED显示数字(十进制,正数)
  * @param  Line 起始行位置,范围:1~4
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~4294967295
  * @param  Length 要显示数字的长度,范围:1~10
  * @retval 无
  */
void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
    uint8_t i;
    for (i = 0; i < Length; i++)
    {
        OLED_ShowChar(Line, Column + i, Number / OLED_Pow(10, Length - i - 1) % 10 + '0');
    }
}

/**
  * @brief  OLED显示数字(十进制,带符号数)
  * @param  Line 起始行位置,范围:1~4
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:-2147483648~2147483647
  * @param  Length 要显示数字的长度,范围:1~10
  * @retval 无
  */
void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length)
{
    uint8_t i;
    uint32_t Number1;
    if (Number >= 0)
    {
        OLED_ShowChar(Line, Column, '+');
        Number1 = Number;
    }
    else
    {
        OLED_ShowChar(Line, Column, '-');
        Number1 = -Number;
    }
    for (i = 0; i < Length; i++)
    {
        OLED_ShowChar(Line, Column + i + 1, Number1 / OLED_Pow(10, Length - i - 1) % 10 + '0');
    }
}

/**
  * @brief  OLED显示数字(十六进制,正数)
  * @param  Line 起始行位置,范围:1~4
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~0xFFFFFFFF
  * @param  Length 要显示数字的长度,范围:1~8
  * @retval 无
  */
void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
    uint8_t i, SingleNumber;
    for (i = 0; i < Length; i++)
    {
        SingleNumber = Number / OLED_Pow(16, Length - i - 1) % 16;
        if (SingleNumber < 10)
        {
            OLED_ShowChar(Line, Column + i, SingleNumber + '0');
        }
        else
        {
            OLED_ShowChar(Line, Column + i, SingleNumber - 10 + 'A');
        }
    }
}

/**
  * @brief  OLED显示数字(二进制,正数)
  * @param  Line 起始行位置,范围:1~4
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  * @param  Length 要显示数字的长度,范围:1~16
  * @retval 无
  */
void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
    uint8_t i;
    for (i = 0; i < Length; i++)
    {
        OLED_ShowChar(Line, Column + i, Number / OLED_Pow(2, Length - i - 1) % 2 + '0');
    }
}

/**
  * @brief  OLED初始化
  * @param  无
  * @retval 无
  */
void OLED_Init(void)
{
    uint32_t i, j;

    for (i = 0; i < 1000; i++)          //上电延时
    {
        for (j = 0; j < 1000; j++);
    }

    OLED_I2C_Init();            //端口初始化

    OLED_WriteCommand(0xAE);    //关闭显示

    OLED_WriteCommand(0xD5);    //设置显示时钟分频比/振荡器频率
    OLED_WriteCommand(0x80);

    OLED_WriteCommand(0xA8);    //设置多路复用率
    OLED_WriteCommand(0x3F);

    OLED_WriteCommand(0xD3);    //设置显示偏移
    OLED_WriteCommand(0x00);

    OLED_WriteCommand(0x40);    //设置显示开始行

    OLED_WriteCommand(0xA1);    //设置左右方向,0xA1正常 0xA0左右反置

    OLED_WriteCommand(0xC8);    //设置上下方向,0xC8正常 0xC0上下反置

    OLED_WriteCommand(0xDA);    //设置COM引脚硬件配置
    OLED_WriteCommand(0x12);

    OLED_WriteCommand(0x81);    //设置对比度控制
    OLED_WriteCommand(0xCF);

    OLED_WriteCommand(0xD9);    //设置预充电周期
    OLED_WriteCommand(0xF1);

    OLED_WriteCommand(0xDB);    //设置VCOMH取消选择级别
    OLED_WriteCommand(0x30);

    OLED_WriteCommand(0xA4);    //设置整个显示打开/关闭

    OLED_WriteCommand(0xA6);    //设置正常/倒转显示

    OLED_WriteCommand(0x8D);    //设置充电泵
    OLED_WriteCommand(0x14);

    OLED_WriteCommand(0xAF);    //开启显示

    OLED_Clear();               //OLED清屏
}

#pragma vector = USCI_B0_VECTOR;
__interrupt void USCI_B0_ISR(void)
{
    switch (__even_in_range(UCB0IV, 12))
    {
        case USCI_I2C_UCTXIFG:
            if (LastByteFlag == 0)
            {
                USCI_B_I2C_masterSendMultiByteNext(USCI_B0_BASE, I2C_Tx_BufData);
                LastByteFlag = 1;
            }
            else if (LastByteFlag == 1)
            {
                USCI_B_I2C_masterSendMultiByteStop(USCI_B0_BASE);
                USCI_B_I2C_clearInterrupt(USCI_B0_BASE, USCI_B_I2C_TRANSMIT_INTERRUPT);
                __bic_SR_register_on_exit(LPM0_bits);
            }
            break;
        default:
            break;
    }
}

  • main.c
#include <driverlib.h>
#include "OLED.h"


void Delay_ms(int x_ms)
{
    while (x_ms--)
    {
        /* 执行一次__delay_cycles()函数,延时时间T = 1 / f_MCLK */
        __delay_cycles(1000 * 25);  // MCLK = 25MHz,是原来1MHz的25倍
    }
}

void SystemClock_Init(void)
{
    PMM_setVCore(PMM_CORE_LEVEL_3);     //高主频工作需要较高的核心电压

    //XT1引脚复用
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN4);
    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN5);

    //起振XT1
    UCS_turnOnLFXT1(UCS_XT1_DRIVE_3, UCS_XCAP_3);

    //XT2引脚复用
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN2);
    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN3);

    //起振XT2
    UCS_turnOnXT2(UCS_XT2_DRIVE_4MHZ_8MHZ);

    //XT2作为FLL参考时钟,先8分频,再50倍频 4MHz / 8 * 50 = 25MHz
    UCS_initClockSignal(UCS_FLLREF, UCS_XT2CLK_SELECT, UCS_CLOCK_DIVIDER_8);
    UCS_initFLLSettle(25000, 50);

    //XT1作为ACLK时钟源 = 32768Hz
    UCS_initClockSignal(UCS_ACLK, UCS_XT1CLK_SELECT, UCS_CLOCK_DIVIDER_1);

    //DCOCLK作为MCLK时钟源 = 25MHz
    UCS_initClockSignal(UCS_MCLK, UCS_DCOCLK_SELECT, UCS_CLOCK_DIVIDER_1);

    //DCOCLK作为SMCLK时钟源 = 25MHz
    UCS_initClockSignal(UCS_SMCLK, UCS_DCOCLK_SELECT, UCS_CLOCK_DIVIDER_1);

    //设置外部时钟源的频率,使得在调用UCS_getMCLK, UCS_getSMCLK 或 UCS_getACLK时可得到正确值
    UCS_setExternalClockSource(32768, 4000000);
}

/**
 * main.c
 */
int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer

    SystemClock_Init();
    OLED_Init();

    uint8_t count = 0;

    OLED_ShowString(1, 1, "Load Successful!");

    while (1)
    {
        OLED_ShowNum(2, 1, count, 3);
        Delay_ms(500);
        count ++;
    }
}



  持续更新完善中……


  原创笔记,码字不易,欢迎点赞,收藏~ 如有谬误敬请在评论区不吝告知,感激不尽!博主将持续更新有关嵌入式开发、机器学习方面的学习笔记~文章来源地址https://www.toymoban.com/news/detail-599489.html

到了这里,关于MSP430学习笔记(四)丨I2C通信(MSP430F5529驱动OLED显示屏)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • MSP430F5529学习笔记(6)——导入MSP430Ware,查看例程

    MSP430F5529学习笔记(6)——导入MSP430Ware,查看例程

    MSP430WARE下载; 目录 在线版本 下载MSP430Ware 查看例程 导入例程  离线版本 下载MSP430Ware  查看例程 导入例程 MSP430Ware里面有很多例程和库函数使用手册,我们可以查看学习。非常重要 (1) 打开CCS——view——Resource Explorer  之后我们会进入如下界面 (2)  点击MSP430——Embe

    2024年02月13日
    浏览(8)
  • MSP430F5529单片机入门学习笔记1

    MSP430F5529单片机入门学习笔记1

    本笔记整理自B站教程 MSP430F5529单片机学习视频汇总 右边部分写错了,看的时候注意 注意#include“driverlib.h”头文件时要注意: 添加MSP430F5xx_6xx文件夹到当前工程下 MSP430F5xx_6xx文件夹是在导入的msp430ware_3_80_13_03包中找 把上述MSP430F5xx_6xx文件夹的路径包含进来 有三个系统时钟可

    2024年02月06日
    浏览(9)
  • 【2023电赛备赛】msp430f5529学习笔记(一)

    【2023电赛备赛】msp430f5529学习笔记(一)

    【写在前】 本人目前是大二在读生,第一次参加电赛,准备不充分,结果熬了四天,最后成绩却不如人意。有51和32的基础,然后想立一个flag系统的学习一下主打超低功耗的msp430f5529单片机为比赛做准备(毕竟电赛限制TI的板子)。另一方面也是给电协的后继者留下一些参考的

    2024年02月11日
    浏览(10)
  • MSP430F5529 DriverLib 库函数学习笔记(一)时钟配置和闪烁LED

    MSP430F5529 DriverLib 库函数学习笔记(一)时钟配置和闪烁LED

    平台:Code Composer Studio 10.3.1 MSP430F5529 LaunchPad™ Development Kit (MSP‑EXP430F5529LP) (1)5个时钟来源         时钟系统模块具有5个时钟来源。 ① XT1CLK :低频/高频振荡器,可以使用32768Hz的手表晶振、标准晶体、谐振器或4~32MHz的外部时钟源; ② VLOCLK :内部超低功耗低频振荡

    2024年02月16日
    浏览(6)
  • MSP430F5529库函数学习——串口

    MSP430F5529库函数学习——串口

    波特率计算网站;导入MSP430Ware,查看例程;原理图和中文开发手册获取 目录 GPIO_setAsPeripheralModuleFunctionInputPin()和GPIO_setAsPeripheralModuleFunctionOutputPin 函数声明  作用 参数 selectedPort selectedPins 使用 USCI_A_UART_init() 函数声明  作用 参数 baseAddress param  USCI_A_UART_enable() 函数

    2024年02月16日
    浏览(8)
  • I2C用法和MSP430F5299上的I2C

    I2C用法和MSP430F5299上的I2C

    1. 二线传输; 2. 无中心主机; 3. 软件寻址; 4. 应答式数据传输过程; 5. 节点可带点接入或撤出; 6. IIC的SCL和SDA都需要接上拉电阻,保证空闲状态的稳定性; 由主机发出起始信号和停止信号。 起始信号: 当SCL保持为高电平时,SDA产生一个下降沿,则代表起始信号; 停止信

    2024年02月13日
    浏览(6)
  • MSP430F5529库函数GPIO学习

    MSP430F5529库函数GPIO学习

    导入MSP430Ware,查看例程;数据手册以及原理图获取 建议不是很了解寄存器的看完我的MSP430F5529学习笔记  目录 GPIO_setAsOutputPin() 函数声明 作用 参数 selectedPort selectedPins 修改的寄存器 使用 与GPIO_setAsOutputPin()参数一致的函数  GPIO_setOutputHighOnPin() GPIO_setOutputLowOnPin()

    2024年02月15日
    浏览(10)
  • 【MSP430F5529基于库函数的学习】电赛速学及小车实战

    【MSP430F5529基于库函数的学习】电赛速学及小车实战

    为电赛准备学习的MSP430笔记 提示:主要跟着这个大佬学的 一张经常要看的图 时钟配置和闪烁的LED 时钟系统结构 (1)5个时钟来源 时钟系统模块具有5个时钟来源。 ① XT1CLK:低频/高频振荡器,可以使用32768Hz的手表晶振、标准晶体、谐振器或4~32MHz的外部时钟源; ② VLOCLK:

    2024年02月12日
    浏览(7)
  • MSP430F5529——中断理解

    MSP430F5529——中断理解

    认识低功耗模式; MSP430的中断,需要两个部分,一部分是打开中断,另外一部分是编写中断服务函数 首先我们得知道__bis_SR_register和_BIS_SR是一个玩意。查看宏定义可知  _BIS_SR()可传入的参数 然后我们查看x的值,发现里面有八个可以传入的值 我们这里只需要关系GIE就可以

    2024年02月16日
    浏览(4)
  • 05:OLED模块【MSP430F5529】

    05:OLED模块【MSP430F5529】

    目录 实物图 字模取字         字模软件         取模步骤         1.设置软件         2.取模         3.输出数据  代码 type.h oledfont.h oled.h oled.c main.c 下面图片中,可以看到OLED模块的四个接口:GND,VCC,SCL,SDA GND VCC SCL SDA 接地 接电源3.3V/5V 接P3.5 接P3.6       

    2024年02月16日
    浏览(8)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包