MSP430F5529库函数学习与电赛小车实战指南

文章目录

  • 前言
  • 一、void SystemClock_Init(void)//系统初始化
  • 时钟系统结构
  • 二、void Counter_Left_Init (void) //编码器计数
  • 设置外部中断
  • 三、void TimerA1Init()//定时器初始化
  • 定时器中断函数
  • 四、void Motor_Left_Init (void)//PWM初始化
  • 解释一下如何产生pwm
  • 补充一个GPIO的规范用法
  • 五、bool UART_Init(uint16_t baseAddress, uint32_t Baudrate)//串口初始化
  • 通信规则
  • 细解一下这里的参数
  • __even_in_range的使用
  • 简单与openmv通讯
  • 六、OLED_Init()//oled初始化
  • 一个发现(和普及I2C原理)
  • 总结
  • 附件
  • 前言

    为电赛准备学习的MSP430笔记


    提示:主要跟着这个大佬学的


    一张经常要看的图

    一、void SystemClock_Init(void)//系统初始化

    时钟配置和闪烁的LED

    时钟系统结构

    时钟系统结构
    (1)5个时钟来源
    时钟系统模块具有5个时钟来源。
    ① XT1CLK:低频/高频振荡器,可以使用32768Hz的手表晶振、标准晶体、谐振器或4~32MHz的外部时钟源;
    ② VLOCLK:内部超低功耗低频振荡器,典型频率12kHz;
    ③ REFOCLK:内部调整低频参考振荡器,典型值为32768Hz;
    ④ DCOCLK:内部数字时钟振荡器,可由FLL稳定后得到;
    ⑤ XT2CLK:高频振荡器,可以是标准晶振、谐振器或4~32MHz的外部时钟源。
    (2)3个时钟信号
    时钟系统模块可以产生3个时钟信号供CPU和外设使用。
    ① ACLK:辅助时钟(Auxiliary Clock)。可以通过软件选择XT1CLK、REFOCLK、VLOCLK、DCOCLK、DCOCLKDIV或XT2CLK(当XT2CLK可用时)。DCOCLKDIV是FLL模块内DCOCLK经过1/2/4/8/16/32分频后获得的。ACLK主要用于低速外设。ACLK可以再进行1/2/4/8/16/32分频,ACLK/n 就是ACLK 经过1/2/4/8/16/32分频后得到的,也可以通过外部引脚进行输出。
    ② MCLK:主时钟(Master Clock)。MCLK的时钟来源与ACLK相同,MCLK专门供CPU使用,MCLK配置得越高,CPU的执行速度就越快,功耗就越高。一旦关闭MCLK,CPU也将停止工作,因此在超低功耗系统中可以通过间歇启用MCLK的方法降低系统功耗。MCLK也可经1/2/4/8/16/32分频后供CPU使用。
    ③ SMCLK:子系统时钟(Subsystem Master Clock)。SMCLK的时钟来源与ACLK相同,SMCLK主要用于高速外设,SMCLK也可以再进行1/2/4/8/16/32分频。

    MSP430具有高达25Mhz的主频,让我们来配置它

    //将主时钟MCLK,子系统时钟SMCLK设为25Mhz,MCLK主要用于CPU,SMCLK主要用于高速外设
    //将辅助时钟ACLK设为32768Hz,主要用于低速外设
    void SystemClock_Init(void)
    {
        PMM_setVCore(PMM_CORE_LEVEL_3);     //高主频工作需要较高的核心电压
    
        //XT1振荡器的引脚复用  P5.4 XIN输入 P5.5 XOUT输出 选择单片机内部的晶振
        GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN4);
        GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN5);
    
        //起振XT1  若在LF工作下的XT1振荡器为32768hz的低频晶振,与之相匹配为12pf的电容    XCAP(0: 2pf ,1: 5.5pf, 2: 8,5pf, 3:12pf )
        UCS_turnOnLFXT1(UCS_XT1_DRIVE_3,UCS_XCAP_3);
    
        //XT2引脚复用   P5.2 XIN输入 P5.5 XOUT输出 板载XT2晶振为CSTCR4M00G15L99,4MHz
        GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN2);
        GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN3);
    
        //起振XT2
        UCS_turnOnXT2(UCS_XT2_DRIVE_4MHZ_8MHZ);
    
        //XT2作为FLL(锁频环)的时钟源,输出为DCOCLK(内部数字时钟振荡器),8分频                      先8分频,再50倍频 4MHz / 8 * 50 = 25MHz
        UCS_initClockSignal(UCS_FLLREF, UCS_XT2CLK_SELECT, UCS_CLOCK_DIVIDER_8);
        //用于设置锁相环倍频系数,第一个系数为目标主时钟的频率 单位kHz,第二个系数为= 第一个系数/FLL的频率 (既刚刚得到的4Mhz/8)  50 = 25000khz/(0.5M)  1000k= 1M 1M =10^6khz
        UCS_initFLLSettle(25000, 50);
    
        //XT1作为ACLK时钟源 = 32768Hz 1分频= /1
        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时可得到正确值 (XT1CLK_frequency,XT2CLK_frequency)
        UCS_setExternalClockSource(32768, 4000000);
    }
    

    二、void Counter_Left_Init (void) //编码器计数

    GPIO

    电机编码器的线数为11(一圈方波数)30(减速比)=330
    线数太低了,我们使用4倍频来使它加倍,330
    4=1320
    我们需要在AB相的上升下降沿都计数(相当于原来的4倍)

    现在我们用外部中断来实现编码器计数

    设置外部中断

    void Counter_Left_Init (void)
    {
        //配置时,先配置功能选择寄存器PxSEL,
        //若为I/O端口功能,则继续配置方向寄存器PxDIR;
        //若为输入,则继续配置中断使能寄存器PxIE;
        //若允许中断,则继续配置中断触发沿选择寄存器PxIES。
        //只有P1 和P2 有中断功能
    
        //P1.3 P1.6 上拉输入并使能interrupt enabled    使能寄存器需和输出寄存器配合使用,才能完成上拉/下拉电阻的配置。
        GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1,GPIO_PIN3 +GPIO_PIN6);
        GPIO_enableInterrupt(GPIO_PORT_P1,GPIO_PIN3 +GPIO_PIN6);
    
        //设置中断类型 Hi/Lo edge
        GPIO_selectInterruptEdge(GPIO_PORT_P1,GPIO_PIN3,GPIO_HIGH_TO_LOW_TRANSITION|GPIO_LOW_TO_HIGH_TRANSITION);
        GPIO_selectInterruptEdge(GPIO_PORT_P1,GPIO_PIN6,GPIO_HIGH_TO_LOW_TRANSITION|GPIO_LOW_TO_HIGH_TRANSITION);
    
        //清除中断标志位 IFG cleared
        GPIO_clearInterrupt(GPIO_PORT_P1,GPIO_PIN3 +GPIO_PIN6);
    
        //启用可屏蔽中断(具有中断功能的片上外设产生)
        _BIS_SR(GIE);
    
    }
    

    中断函数

    #pragma vector=PORT1_VECTOR     // P1口中断源
    __interrupt
    void Port_1 (void)
    {
    //    if(GPIO_getInterruptStatus (GPIO_PORT_P1, GPIO_PIN3)||GPIO_getInterruptStatus (GPIO_PORT_P1, GPIO_PIN6))
    //    {
    //        Counter_Left++;
    //        GPIO_clearInterrupt(GPIO_PORT_P1,GPIO_PIN3 +GPIO_PIN6);  
    //    }
        _EINT();//恢复总的中断允许,避免中断处理延迟
        if(GPIO_getInterruptStatus(GPIO_PORT_P1, GPIO_PIN3))//当发生中断
        {
            Counter_Left++;
            GPIO_clearInterrupt(GPIO_PORT_P1,GPIO_PIN3);
        }
        if(GPIO_getInterruptStatus(GPIO_PORT_P1, GPIO_PIN6))
        {
            Counter_Left++;
            GPIO_clearInterrupt(GPIO_PORT_P1,GPIO_PIN6);
        }
    }
    
    

    三、void TimerA1Init()//定时器初始化

    定时器A
    我们想实现每秒sec加1

    设得中断频率为25MHz / 10 / 25000 = 100Hz //即每秒刷新100下,0.01s定时
    一共两个中断模式CCR0中断 TAIE中断,一个使能一个不使能
    一般使用增计数模式CCR0中断

    定时器A增计数模式CCR0中断

    //定时0.01s
    void TimerA1Init()
    {
        Timer_A_initUpModeParam param = {0};
        param.clockSource = TIMER_A_CLOCKSOURCE_SMCLK; //时钟源选为SMCLK = 25MHz
        param.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_10;  //10分频
        param.timerPeriod = 25000-1;    //计数值设为25000 - 1
        param.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_DISABLE;   //不使能 TAIE中断
        param.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE;   //使能CCR0中断
        param.timerClear = TIMER_A_DO_CLEAR;  //把定时器的定时计数器,分频计数器的计数值清零
        param.startTimer = true;     //初始化后立即启动定时器
    
        //设得中断频率为25MHz / 10 / 25000 = 100Hz
        Timer_A_initUpMode(TIMER_A1_BASE,&param);   //配置定时器A为增计数模式
    }
    

    定时器中断函数


    例如我们配置定时器1的0寄存器(在32里应该叫通道)
    TIMER_A1_BASE
    TIMER1_A0_VECTOR //向量名和中断函数名必须一致
    TIMER1_A0_ISR //前面的1 是A1的1

    #pragma vector=TIMER1_A0_VECTOR
    __interrupt
    void TIMER1_A0_ISR (void)
    {
        if(n++==100)
        {
            second++;
            n=0;
        }
    }
    

    四、void Motor_Left_Init (void)//PWM初始化

    定时器A

    解释一下如何产生pwm

    Timer_A_outputPWM(uint16_t baseAddress, Timer_A_outputPWMParam ∗param)
    //计时器A运行在增计数模式产生PWM

    为什么说这句话是在增计数模式下呢,我们并没看到配置定时器在增计数模式,所以我们看看这个库函数怎么写的。

    它在第一句把所有位进行了一个清零的操作,然后在第4句将TIMER_A_UP_MODE置1,至此我们知道它将增模式也一起配置了。
    已知增计数模式下是将0加到TAxCCR0再重新计数,我们看到它将TAxCCR0置为我们可以设置的时间周期timerPeriod。dutyCycle是什么呢,下面会解释。

    然后我们在这里将compareOutputMode设置 复位置位 模式

    param.compareOutputMode = TIMER_A_OUTPUTMODE_RESET_SET;


    增计数模式下,定时器比较输出
    在这个模式下,我们发现在计数到TAxCCR1时为高电平输出,TAxCCR1~TAxCCR0时为低电平输出,而TAxCCR1就是我们上文未解释的dutyCycle(占空比),当我们将TAxCCR0设为100,TAxCCR1设为50时,那我们的占空比就为50/100 = 50%。

    我们想实现电机初始化

    P1.2 对应 TA0.1

    void Motor_Left_Init (void)
    {
        //P1.2 as PWM output
        GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN2);//P1.2复用输出
    	//GPIO_setAsOutputPin (GPIO_PORT_P4,GPIO_PIN0 +GPIO_PIN3 );   //GPIO输出
        //GPIO_setOutputHighOnPin (GPIO_PORT_P4, GPIO_PIN0);  //高电位输出
        //GPIO_setOutputLowOnPin (GPIO_PORT_P4, GPIO_PIN3);  //低电位输出
    
        //Generate PWM - Timer runs in Up mode
        Timer_A_outputPWMParam param = {0};
        param.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;      // 时钟源选为SMCLK = 25MHz
        param.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_1;       //不分频
        //装载值设为1000 - 1
        param.timerPeriod =1000-1;      //时钟周期
        //频率为25M/1/1000 = 25000hz
        //P1.2 对应 TA0.1 故设为TIMER_A_CAPTURECOMPARE_REGISTER_1
        param.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_1;      //选择比较寄存器
        param.compareOutputMode = TIMER_A_OUTPUTMODE_RESET_SET; 为
        //pwm最大1000
        param.dutyCycle = 0;//这个值compare = 300 就相当于300/1000 30%的占空比
        Timer_A_outputPWM(TIMER_A0_BASE, &param);
    }
    

    Timer_A_setCompareValue(uint16_t baseAddress, uint16_t compareRegister, uint16_t
    compareValue)
    //设置捕获比较寄存器的值

    void Motor_SetSpeed_Left(int8_t Speed)
    {
    	GPIO_setAsOutputPin (GPIO_PORT_P4,GPIO_PIN0 +GPIO_PIN3 );//初始化GPIO输出
    	if (Speed >= 0)  //正数 代表正转
    	{
       		
       		GPIO_setOutputHighOnPin (GPIO_PORT_P4, GPIO_PIN0);  //高电位输出
        	GPIO_setOutputLowOnPin (GPIO_PORT_P4, GPIO_PIN3);  //低电位输出
    		Timer_A_setCompareValue(TIMER_A0_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_1, Speed)
    	}
    	else
    	{
    		GPIO_setOutputLowOnPin (GPIO_PORT_P4, GPIO_PIN0);  //高电位输出
        	GPIO_setOutputHighOnPin (GPIO_PORT_P4, GPIO_PIN3);  //低电位输出
    		Timer_A_setCompareValue(TIMER_A0_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_1, -Speed)//因为SetCompare要传的是无符号整型数 所以 speed加负号
    	}
    }
    

    最终输出速度,小车开始转

    void Front_Run(void)
    {
        Motor_SetSpeed_Left(300);
        Motor_SetSpeed_Right(300);
    }
    

    补充一个GPIO的规范用法


    首先我们对引脚配置输入或是输出

    GPIO_setAsOutputPin(uint8_t selectedPort, uint16_t selectedPins);
    GPIO_setAsInputPin(uint8_t selectedPort, uint16_t selectedPins);
    GPIO_setAsInputPinWithPullDownResistor(uint8_t selectedPort, uint16_t selectedPins);
    GPIO_setAsInputPinWithPullUpResistor(uint8_t selectedPort, uint16_t selectedPins);
    GPIO_setDriveStrength(uint8_t selectedPort, uint16_t selectedPins, uint8_t
    driveStrength);
    GPIO_setAsPeripheralModuleFunctionOutputPin(uint8_t selectedPort, uint16_t
    selectedPins);
    GPIO_setAsPeripheralModuleFunctionInputPin(uint8_t selectedPort, uint16_t
    selectedPins);
    
    

    GPlO引脚可以被配置为在外设模块中操作,通过使用配置GPIO分配功能

    GPIO_setOutputHighOnPin(uint8_t selectedPort, uint16_t selectedPins);
    GPIO_setOutputLowOnPin(uint8_t selectedPort, uint16_t selectedPins);
    GPIO_toggleOutputOnPin(uint8_t selectedPort, uint16_t selectedPins);
    GPIO_getInputPinValue(uint8_t selectedPort, uint16_t selectedPins);
    
    

    一般在程序的初始化阶段对端口进行配置。
    配置时,先配置功能选择寄存器PxSEL,
    若为I/O端口功能,则继续配置方向寄存器PxDIR;
    若为输入,则继续配置中断使能寄存器PxIE;
    若允许中断,则继续配置中断触发沿选择寄存器PxIES。

    简单配置电机的两个引脚 ,第一句必不可少

       
        GPIO_setAsOutputPin (GPIO_PORT_P4,GPIO_PIN0 +GPIO_PIN3 );   //GPIO输出
        GPIO_setOutputHighOnPin (GPIO_PORT_P4, GPIO_PIN0);  //高电位输出
        GPIO_setOutputLowOnPin (GPIO_PORT_P4, GPIO_PIN3);  //低电位输出
    
    

    五、bool UART_Init(uint16_t baseAddress, uint32_t Baudrate)//串口初始化

    UART通信
    P3.3(TX)和P3.4(RX)为USCI_A0串口
    P4.4(TX)和P4.5(RX)为USCI_A1串口

    通信规则

    如图所示,异步通信字符格式由5个部分组成:一个起始位、7位或8位数据位、一个奇/偶/无校验位、一个地址位和一个或两个停止位。其中,用户可以通过软件设置数据位、停止位的位数,还可以设置奇偶校验位的有无。通过选择时钟源和波特率寄存器的数据来确定传输速率。UCMSB控制位用来设置传输的方向和选择最低位还是最高位先发送。一般情况下,对于UART通信选择先发送最低位。

    USCI_A_UART_clearInterrupt(uint16_t baseAddress, uint8_t mask)
    //清除UART中断源,使其不再断言。当使用中断向量生成器时,最高中断标志将自动清除
    USCI_A_UART_enableInterrupt(uint16_t baseAddress, uint8_t mask)
    //启用UART中断

    细解一下这里的参数

    huart.parity = USCI_A_UART_NO_PARITY;
    //设置奇偶校验位,USCI_A_UART_ODD_PARITY奇校验    USCI_A_UART_EVEN_PARITY偶校验  USCI_A_UART_NO_PARITY 无校验位
    huart.msborLsbFirst = USCI_A_UART_LSB_FIRST;
    //设置最低最低位优先或最高位优先的数据发送和接收方式 通常我们接收数据中的最低位
    //LSB(Least Significant Bit)是“最低有效位”。MSB(Most Significant Bit)是“最高有效位”。
    huart.numberofStopBits = USCI_A_UART_ONE_STOP_BIT;
    //设置停止位 USCI_A_UART_ONE_STOP_BIT 一位USCI_A_UART_TWO_STOP_BITS 两位
    huart.uartMode = USCI_A_UART_MODE;
    //选择模式 选取默认的异步通讯模式 当三个或多个设备通信时,
    USCI支持空闲行    USCI_A_UART_IDLE_LINE_MULTI_PROCESSOR_MODE和
    地址位多处理器通信格式    USCI_A_UART_ADDRESS_BIT_MULTI_PROCESSOR_MODE
    还一个模式为自动波特率检测	USCI_A_UART_AUTOMATIC_BAUDRATE_DETECTION_MODE
    

    第一个参数为选择串口基地址,第二个参数为波特率

    bool UART_Init(uint16_t baseAddress, uint32_t Baudrate)
    {
        float UART_Temp = 0;
    
        USCI_A_UART_initParam huart = {0};
    
        //将所用引脚复用为UART模式
        if(baseAddress == USCI_A0_BASE)         //P3.3, P3.4 = USCI_A0 TXD/RXD
        {
            GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P3, GPIO_PIN3);
            GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P3, GPIO_PIN4);
        }
        else if(baseAddress == USCI_A1_BASE)    //P4.4, P4.5 = USCI_A1 TXD/RXD
        {
            GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P4, GPIO_PIN4);
            GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4, GPIO_PIN5);
        }
        //当目标波特率较低时,UART选用时钟源为ACLK,反之选择SMCLK
        //调用UCS_getACLK/UCS_getSMCLK前需正确调用UCS_setExternalClockSource函数,我已加到SystemClock_Init函数中
        if(Baudrate <= 9600)
        {
            huart.selectClockSource = USCI_A_UART_CLOCKSOURCE_ACLK;
            UART_Temp = (float)UCS_getACLK()/Baudrate;
        }
        else
        {
            huart.selectClockSource = USCI_A_UART_CLOCKSOURCE_SMCLK;
            UART_Temp = (float)UCS_getSMCLK()/Baudrate;
        }
    
        if(UART_Temp < 16)  //当分频因子小于16时,采用低频波特率设置
            huart.overSampling = USCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION;
        else    //反之,采用过采样波特率设置
        {
            huart.overSampling = USCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION;
            UART_Temp /= 16;
        }
    
        huart.clockPrescalar = (int)UART_Temp;
    
        if(huart.overSampling == USCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION)
        {   //低频波特率设置   UCBRSx
            huart.secondModReg = (int)((UART_Temp - huart.clockPrescalar) * 8);
        }
        else
        {   //过采样波特率设置 UCBRFx
            huart.firstModReg = (int)((UART_Temp - huart.clockPrescalar) * 16);
        }
    
        huart.parity = USCI_A_UART_NO_PARITY;
        huart.msborLsbFirst = USCI_A_UART_LSB_FIRST;
        huart.numberofStopBits = USCI_A_UART_ONE_STOP_BIT;
        huart.uartMode = USCI_A_UART_MODE;
    
        if (STATUS_FAIL == USCI_A_UART_init(baseAddress, &huart)) //如果成功返回一个STATUS_SUCCESS
        {   //初始化对应串口
            return STATUS_FAIL;
        }
    
        //Enable UART module for operation 使能对应串口
        USCI_A_UART_enable(baseAddress);
    
        //Enable Receive Interrupt 启用串口中断
        USCI_A_UART_clearInterrupt(baseAddress, USCI_A_UART_RECEIVE_INTERRUPT);
        USCI_A_UART_enableInterrupt(baseAddress, USCI_A_UART_RECEIVE_INTERRUPT);
    
        return STATUS_SUCCESS;
    }
    

    串口中断函数

    USCI_A_UART_transmitData(uint16_t baseAddress, uint8_t transmitData)
    //通过UART模块传输一个字节
    USCI_A_UART_receiveData(uint16_t baseAddress)
    //接收一个已发送到UART模块的字节。

    下面实现将接收到的字符回传 接收一个字符就回发一个

    #pragma vector=USCI_A0_VECTOR
    __interrupt void USCI_A0_ISR (void)
    {
        uint8_t receivedData = 0;
        switch (__even_in_range(UCA0IV,4))
        {
            //Vector 2 - RXIFG
            case 2:
                receivedData = USCI_A_UART_receiveData(USCI_A0_BASE);
                USCI_A_UART_transmitData(USCI_A0_BASE,receivedData);
                break;
            default:
                break;
        }
    }
    

    __even_in_range的使用

    MSP430之__even_in_range
    使用__even_in_range 的好处是可以生成效率比较高的代码,在判断多中断源的中断的来源时可以使用此函数。
    原型:unsigned short __even_in_range(unsigned short value, unsignedshort upper_limit);

    功能:只能与switch 语句结合使用,判断value 是否为偶数且小于等于upper_limit。

    简单与openmv通讯

    之前已经配置好了串口,
    在库函数中,没有相关的函数配置发送数据位数。只在注释里找到。


    从手册里发现默认是8位数据位,

    所以我们msp430串口的相关配置是:8位数据位,无奇偶校验,1位停止位

    UART_Init(USCI_A1_BASE, 115200);//做一个115200的初始化
    

    同样,我们在openmv的也进行相同操作

    from pyb import UART
    uart = UART(3,115200)   #定义串口3变量 #P4 P5
    uart.init(115200, bits=8, parity=None, stop=1) # init with given parameters
    # 8位数据位 无奇偶校验 1位停止位
    

    最后openmv的数据传给msp430

    uart.write(str(output))
    

    我们要实现在openmv的ide里知道是否已经传到msp430,所以我们打印从msp430回传的数据

    def recive_data():
        global uart
        if uart.any():
            tmp_data = uart.readline();
            print(tmp_data)
     recive_data();
    

    六、OLED_Init()//oled初始化

    库函数I2C驱动OLED屏幕
    我们用四针脚的oled来显示,5529芯片上的资源有
    P3.0 SDA //P3.1SCL
    P4.1SDA //P4.2SCL
    看上面的博客的需要改端口的在这可以改

    也可以参考下面这个博客
    OLED模块//用这个可以点亮 试过
    然后在这个位置修改

    一个发现(和普及I2C原理)

    先搞懂一下I2C协议,这个博主讲的非常明白
    I2C协议靠这16张图彻底搞懂(超详细)
    然后我从发现P3.5 P3.6在芯片手册上明明没有标注有SDA功能,却可以当作SDA,SCL来用,于是深究这个问题,这个是类似的博客发的驱动oled代码

    我先找到一篇博客,TI – MCU – MSP430使用指南14 -> I2C通信(eUSCI),上面说eUSCI_B有追加IIC的功能,手册上也雀实有,不过还是没有讲能用的资源有多少,
    于是我开始回到GPIO的引脚上思索这个问题,SDA是双向时钟线
    也就意味着双方的两个引脚必须都要有写和读的功能,而MSP430所有的引脚都有写和读的功能,所以我觉得所有的引脚都可以配置成IIC的SDA、SCL,不过这只是我的一个猜测,具体要是有不对的地方,望指正。

    然后P1~P2还有中断的功能。


    总结

    以上就是今天要讲的内容,本文仅仅简单介绍了MSP430的使用,至此小车是可以跑起来了,为电赛强制用TI的板子做了一个简单的备战。
    最后感谢一下女朋友望月12138写的代码。

    附件

    以下是找的一些MSP430F5529的资料
    链接:https://pan.baidu.com/s/1nGVduyZzR0xHqeAV6XStqA?pwd=dwuv
    提取码:dwuv

    物联沃分享整理
    物联沃-IOTWORD物联网 » MSP430F5529库函数学习与电赛小车实战指南

    发表评论