写在前面:

写下这篇东西的目的首先是希望自己以后忘记MSP430如何使用的时候,能够在看到这篇记录之后能够迅速想起。其次,也希望能够为其他同学或者有需要的人提供一点帮助,话不多说,下面开始正文。

目录

一、开发环境

二、学习方式

三、程序学习

1、点灯

2、LED闪烁

呼吸灯

3、时钟配置

4、定时器

5、外部中断

6、Uart

7、OLED显示

8、超声波

最后

附录


一、开发环境

现在网上提到的一般有CCSIARGCC,KEIL,每种开发环境在CSDN上面应该都能找到相应的搭建方法,我学习MSP430也只是为了应付电赛,相应的也就能倾向于使用TI自己出的开发平台CCS 比较方便 (这里附上链接:CCSTUDIO IDE、配置、编译器或调试器 | TI.com.cn)。下载安装完成之后,无需再配置什么东西,即可开始对于MSP430的开发了。

二、学习方式

临近电赛,本来是想要在B站或者其他学习网站上面找一些相关视频来快速入门,但是后面觉得网上的教学视频质量参差不齐,而且专门针对F5529的视频比较少。所以在这里以文章的形式,让大家可以快速的上手MSP430F5529。

网上的视频中有很大一部分都是采用的driverlib库函数来写的,我当时因为各种奇奇怪怪的原因,始终用不了driverlib同时也发现430的寄存器配置好像也不是很难,就决定使用寄存器配置MSP430了。

做出选择很简单,只是一两秒的事情。但真的想要上手寄存器配置,还是需要花费大量的时间的。这里推荐硬禾学堂上面的中央民族大学信息工程学院教授王继业老师讲的入门MSP430的视频(附上链接:MSP430单片机原理(一个简易版的微机原理)),当时看了真的是受益良多。B站上面也有很多同学讲解了寄存器配置的视频,这里就不举例了,有想法的同学自己去找一找。

使用寄存器配置MSP430,除了根据网上的资料来了解一些常用的寄存器是什么东西,怎么配置之外,我们还需要另一种东西:MSP430的 user’s guid 和 datasheet (在官网上面搜索你使用的430型号,就可以找到相应的用户手册啦~)。这两个分别可以让我们了解我们手上的芯片里面有哪些寄存器寄存器的使用方法;芯片的一些管脚功能重要参数等等。在比赛途中,如果网上找不到自己对应芯片已经写好的例程,那么会用用户手册是十分必要的。

东西准备齐全之后,就让我们一步步来写关于MSP430的代码吧!

三、程序学习

1、点灯

相信我们学习任何一门语言,都是先来一遍Hello World! ,学习一款新的单片机,往往第一步就是点灯。下面来看程序:

void main()
{/*stop watch dog timer*/WDTCTL = WDTPW | WDTHOLD;/*led1,p1.0*/P1DIR |= BIT0;/*熄灭状态*/
//    P1OUT &= ~BIT0; /*点亮状态*/P1OUT |= BIT0;  while(1){;}
}

MSP430配置IO ,PxDIR寄存器来设置是输入还是输出,为了避免影响其他的IO口,我们一般采用的是 |=  。BIT0 代表的就是我们使用的是第0脚,具体含义可以自己查看定义。意思就是根据相关寄存器的定义,将想要设置为输出的IO口的位置置1,就可以了。

2、LED闪烁

想要LED闪烁的方法有很多,这里直接在while循环里面改变LED输出状态就可以实现反转。

代码如下:

void main(void)
{WDTCTL = WDTPW | WDTHOLD; // stop watchdog timerP1DIR |= BIT0;P4DIR |= BIT7;P1OUT |= BIT1;P4OUT |= BIT7;while(1){P1OUT ^= BIT0;delay_ms(60);P4OUT ^= BIT7;delay_ms(60);}
}

关于延时函数,我看网上大多是采用的__delay_cycles();来完成延时的,这里用的是宏定义,代码如下:

#define CPU_F ((double)1000000)
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))//重新定义延时函数
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))

需要注意的是,如果我们没有主动配置时钟源,那么默认是1Mhz,如果修改了时钟频率,那么上面的代码应该也需要对应修改的。

呼吸灯

我们在学习PWM过程中,呼吸灯也是我们比较基础的东西,那怎么才能实现LED呼吸灯的效果呢?

一般为了准确的控制占空比,我们还是需要用到定时器的。

void TimeA0__PWM_Init(void)
{P1SEL |= BIT3; //IO口复用P1DIR |= BIT3;TA0CTL = TASSEL__SMCLK  + MC_3; //SMCLK,增减模式,计数到CCR0处TA0CCR0 = 0x00ff;   //都设置为00ffH,则初始占空比为0TA0CCR2 = 0x00ff; //占空比(TACCR0 - TACCR2) / TACCR0,频率 = SMCLK / (TACCR0 + 1) / 2TA0CCTL2 = OUTMOD_6; //选择比较模式,模式6:Toggle/set}int cnt;
int main(void)
{WDTCTL = WDTPW | WDTHOLD; // stop watchdog timerTimeA0__PWM_Init();while(1){for(cnt=0;cnt < 0x00ff;cnt++){TA0CCR2 = cnt;__delay_cycles(5000);}for(cnt=0x00ff;cnt > 0;cnt--){TA0CCR2 = cnt;__delay_cycles(5000);}}}

通过在while循环里面不断改变CNT的值,从而实现占空比的不断改变,大家对这个方法应该都是比较熟悉的。

3、时钟配置

对于MSP430来说,时钟的配置是十分的复杂的,相信大部分童鞋希望的是直接配置成想要的时钟频率对吧?这里为了节省大家时间,直接附上一份CSDN上大佬的配置时钟文章链接:(MSP430F5529系统时钟频率设置---超频40MHz_Coder_BCM的博客-CSDN博客)

这是大佬的超级代码:

void Clock_Init(unsigned char Fre)//修改主频程序
{/*开启外部两个时钟*/P5SEL |= BIT2|BIT3|BIT4|BIT5;UCSCTL6 |= XCAP_3|XT1OFF;          // XT1 相关 配置UCSCTL6 |= XT2DRIVE_0 |XT2OFF;     // XT2 相关 配置/*以下是提升核心电压部分的代码*/PMMCTL0_H = 0xA5;                                          //开PMM电源管理SVSMLCTL |= SVSMLRRL_1 + SVMLE;                            //配置SVML电压PMMCTL0 =  PMMPW + PMMCOREV_3;                             //配置内核电压while((PMMIFG & SVSMLDLYIFG ) == 0);                       //等待设置完成PMMIFG &= ~(SVMLVLRIFG + SVMLIFG + SVSMLDLYIFG);if((PMMIFG & SVMLIFG) == 1)                                //判断内核电压是否上升到while((PMMIFG & SVMLVLRIFG) == 0);                         //如果没有等待SVSMLCTL &= ~SVMLE;                                        //关掉SVML模块PMMCTL0_H = 0X00;__bis_SR_register(SCG0);                 //该语法为固定格式,意为将括号内的变量置位,UCSCTL0 = 0;                             //先清零,FLL 运行时,该寄存器系统会自动配置,UCSCTL6 = (UCSCTL6&(~(XT2OFF|XT1OFF))|XCAP_3|XT2DRIVE_0);UCSCTL3 = (5<<4)|(2<<0);                 //选择 XTAL2 的时钟信号作为参考信号 并且分频到UCSCTL4|= SELA_5;                        //选择 XTAL2 的时钟信号作为参考信号if(Fre < 5)UCSCTL1 = DCORSEL_2;else if(Fre<15)UCSCTL1 = DCORSEL_4;elseUCSCTL1 = DCORSEL_7;UCSCTL2 = (Fre-1);__bic_SR_register(SCG0);__delay_cycles(782000);while (SFRIFG1 & OFIFG) {                               // Check OFIFG fault flagUCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);           // Clear OSC flaut FlagsSFRIFG1 &= ~OFIFG;                                    // Clear OFIFG fault flag}UCSCTL4 = UCSCTL4&(~(SELS_7|SELM_7))|SELS_3|SELM_3;
}

体验是非常良好的,建议大家都去看看大佬文章里具体是怎么实现的。但我在使用途中出现了一个问题,我将主频设置到了40Mhz之后,Uart最高的频率只能20Mhz,这导致我无法再使用Uart,我尝试过使用其他的时钟源,但是效果都不理想,后面因为时间问题,没有时间仔细琢磨了,就直接将主频设置为20Mhz使用了。如果有同学知道这个问题怎么解决,可以在评论区说明一下~~。

4、定时器

看到这里,相信大家对于MSP430都有一个简单的理解了,其实和其他的单片机差不多,都含有各种外设,只是配置的方式有些许变化而已,一通万通!

F5529的定时器有TimerA 和 TimerB ,两个定时器下面还能细分,这里就不再过多介绍,大家不清楚的自行CSDN。。。 ,我们一般使用的是基本定时功能,PWM输出用来驱动电机。代码如下:

//基本定时器配置
void TimerA1_Init(void)
{TA1CTL = TASSEL_2 + TACLR + MC_1;//SMCLK,增计数模式,计数到CCR0处TA1CCTL0 = CCIE;         //捕获/比较中断使能TA1CCR0  = 19999;        //设定计数值20000, 20Mhz耗时1msTA1CTL  &= ~TAIFG;       //清除标志位
}
/** 功能:初始化PWM*/void PWM_Init(void)
{/*设置P1.2/3/4/5为输出*/P1DIR |= BIT2 + BIT3 + BIT4 + BIT5;/*复用IO为PWM输出*/P1SEL |= BIT2 + BIT3 + BIT4 + BIT5;/*设置自动重装载值Period*/TA0CCR0 |= PWM_Period ; //设置为800,为10KHZ的PWM/*选择时钟为SMCLK,计数模式为增计数模式*/TA0CTL |= TASSEL_2 + MC_1 + TACLR;/*设置PWM的输出模式为模式7*/TA0CCTL1 |= OUTMOD_7;TA0CCTL2 |= OUTMOD_7;TA0CCTL3 |= OUTMOD_7;TA0CCTL4 |= OUTMOD_7;
}

这里需要说明一下的是,我是使用PWM来驱动电机的,两路PWM可以驱动一个减速电机,这里配置了四路,驱动两个电机。

/** @brief:设置PWM占空比*/
void set_pwm(int Motor ,int PWM)
{switch (Motor){case 1: if(PWM > 0) {TA0CCR1 = PWM; TA0CCR2 = 0;} else{TA0CCR1 = 0; TA0CCR2 = -PWM;} break;case 2: if(PWM > 0) {TA0CCR3 = 0; TA0CCR4 = PWM;} else {TA0CCR3 = -PWM; TA0CCR4 = 0;} break;default: TA0CCR1 = 0; TA0CCR2 = 0;TA0CCR1 = 0; TA0CCR2 = 0; break;}}

通过设置占空比的值,来达到控制电机速度以及正反转,说到这里不得不吐槽一下某宝上某趣买的电机真的不好用,设计的跟个鬼一样。。。 ,当然,如果你觉得这里设置占空比直接填数字不方便直观,还可以简单的映射一下。

关于这个编码器测速,我尝试了一下之后,但是感觉效果不是很理想,最终没有使用编码器,这里就不多说了,有兴趣的同学可以自己尝试一下。

差点忘记了,我们配置完定时器,肯定是要写相应的中断函数的,代码如下:

#pragma vector = TIMER1_A0_VECTOR
__interrupt void TIMER1_TA0_ISR(void)
{static uint16_t cnt = 0;if(TAIFG){cnt++;if(cnt == 1000) {P1OUT ^= BIT0 ; cnt = 0;}}TA0CTL ^= TAIFG;
}

不同的中断,中断向量是不一样的,对于不同的中断函数,要填写对应的中断向量。记得一定要清除标志位,不然会出现程序一直在中断的情况!!!

5、外部中断

在LP板上,我们一般需要对两个按键写对应的外部中断,来对应表示我们按键按下做一些事情。代码如下:

void Key_Init(void)
{/*配置P2.1*/P2DIR &= ~BIT1;          //设置P2.1口为输入P2IN |= BIT1;P2REN |= BIT1;/*配置P2.1,开启中断*/P2OUT |= BIT1;          //配置P2.1上拉电阻P2IE |= BIT1;           //P2.1中断使能P2IES |= BIT1;          //P2.1下降沿触发中断P2IFG &= ~BIT1;        //清除中断标志位/*配置P1.1*/P1DIR &= ~BIT1;          //设置P1.1口为输入P1IN |= BIT1;P1REN |= BIT1;/*配置P1.1,开启中断*/P1OUT |= BIT1;          //配置P1.1上拉电阻P1IE |= BIT1;           //P1.1中断使能P1IES |= BIT1;          //P1.1下降沿触发中断P1IFG &= ~BIT1;        //清除中断标志位_EINT();}#pragma vector = PORT2_VECTOR
__interrupt void P2_ISR(void)
{uint16_t a;if(P2IFG & BIT1)  //判断是否是P2.1产生的中断{P2IFG &= ~BIT1;if((P2IN&BIT1)==0){for(a=0;a<=1000;a++);  //按键的消抖功能if((P2IN&BIT1) == 0){               led3_start();}}}P2IFG &= ~BIT1;
}#pragma vector = PORT1_VECTOR
__interrupt void P1_ISR(void)
{uint16_t a;if(P1IFG & BIT1)  //判断是否是P1.1产生的中断{P1IFG &= ~BIT1;if((P1IN&BIT1) == 0){for(a=0;a<=1000;a++);  //按键的消抖功能if((P1IN&BIT1) == 0){P4OUT ^= BIT7;}}}P1IFG &= ~BIT1;
}

一般情况下,我们都是需要在主函数里面开启总中断的,开启总中断的表达方式有很多,我一般是用_EINT(); 。

如果,我们需要一个按键来让小车开始跑起来,那么就需要在按键的中断里写上相应的代码。

6、Uart

串口往往是必不可少的,本次电赛小车题,我们就采用了蓝牙进行通信,效果还算不错,代码如下:

uint16_t ReBuf[20] = {0};
uint8_t rec_yes = 0;/** @Brief: Initialize the Uart and set the baud rate*/
void Uart_Init(void)
{/*使能P4.4/P4.5端口复用*/P4SEL    |= BIT4+BIT5 ;/*Uart Init*/UCA1CTL1 |= UCSWRST; //复位USCI_A1UCA1CTL1 |= UCSSEL__SMCLK; //选择SMCLK为Uart时钟源@1MhzUCA1BR0  |= 0x23;UCA1BR1  |= 0x08; //see user's guid. bps set as 9600@1MhzUCA1MCTL |= UCBRS2 + UCBRF_0; //UCBRS = 1,UCBRF = 0/*清除复位,使能Uart*/UCA1CTL1 &= ~UCSWRST;/*使能中断*/UCA1IE |= UCRXIE; //开启接收中断UCA1IFG &= ~UCRXIFG; //清除中断标志位_EINT();   //使能总中断}void Send_String(uint8_t *Ptr)
{while(*Ptr != '\0'){while((UCA1STAT & UCBUSY)); //当上一个还没发送完成后,先卡在这里UCA1TXBUF = *Ptr;Ptr++;}
}void Send_float(double num)
{uint8_t charbuff[] = {0,'.',0,0,0};uint16_t temp = (uint16_t)(num * 1000);charbuff[0] = (uint8_t)(temp / 1000) + '0';charbuff[2] = (uint8_t)((temp % 1000) / 100) + '0';charbuff[3] = (uint8_t)((temp % 100) / 10) + '0';charbuff[4] = (uint8_t)(temp % 10) + '0';Send_String(charbuff);}void Print_Num(uint16_t Num)
{uint8_t Buf[7] = {0,0,0,0,0,'\r','\n'},cnt;for(cnt = 0;cnt < 5 ; cnt++){Buf[4-cnt] = (uint8_t)(Num%10 + '0');Num /= 10;}Send_String(Buf);
}#pragma vector = USCI_A1_VECTOR
__interrupt void USCI_A1(void)
{static uint8_t cnt = 0;switch(_even_in_range(UCA1IV,4)){case 0:break; // No interrupt pendingcase 2:UCA1TXBUF = UCA1RXBUF;    //将接收到的数据发送出去/*将接收到的数据存储起来,可以通过处理来对外设进行控制*/UCA1IFG &= ~UCRXIFG; //Reset UCRXIFGReBuf[cnt++] = UCA1RXBUF;cnt %= 20;if(ReBuf[cnt - 1] == '\0') //如果数据接收完成{cnt = 0;rec_yes = 1; //接收完成标志}rec_yes = 0;break;case 4:break; //TXIFGdefault:break;}
}

F5529的串口有两个,现在配置的这一个串口可以直接用USB连接电脑进行数据收发,如果不想使用USB,就需要拔掉板子上面的跳线帽了,另一个串口的配置大致相同,只是需要更改IO引脚与之对应。

在中断函数里面,我们对于多个中断源共同使用一个中断向量的情况,常常使用switch来判断产生中断的是哪一个。

如果想要更改波特率和时钟源,更改这三个就好了,具体更改细节请查看用户手册或者CSDN。

UCA1CTL1 |= UCSSEL__SMCLK;
UCA1BR0  |= 0x23;
UCA1BR1  |= 0x08;

7、OLED显示

OLED的显示其实都是在网上找的代码直接CV的,代码长,比较占空间,这里就不过多讲解,我会在文末放上工程链接,以供参考,有需要的童鞋可以自取。

8、超声波

超声波同样是在网上找的代码,在比赛过程中,引脚冲突了,所以更换了引脚。为了显示方便,将测量精度保持在CM,整体来说效果不错,需要注意的是,我采用的主频是20Mhz,所有代码都是再次基础之上完成的,如果你不是采用的20M,那么算距离的时候也应该进行修改,具体的方法可以CSDN,这里也不过多提及。

#define Trig1(a)  if(a==1) P2OUT |= BIT2; else P2OUT &= ~BIT2unsigned int cap_new = 0;           // 首次捕捉的ta0r值
unsigned int cap_old = 0;           // 二次捕捉的ta0r值char cap_N = 0;                     // 溢出次数
char state = 0x00;                  // zhuangtai
uint16_t cap_data = 0;                  // 距离值/**  P7.4为echo引脚             捕获模式*  P2.2 为Trig          数字i/o模式*/
void Hc_sr_Init(void)           // 超声波模块初始化
{P7OUT &= ~( BIT2 + BIT4 );P2DIR |=  BIT2;P7SEL |=  BIT4;TB0CTL   = TBSSEL__SMCLK + ID__8 + MC_2 + TBCLR + TBIE;TB0CCTL2 = CM_1 + SCS +CAP + CCIE + CCIS_0;
}void Hc_sr_Open(void)           //生成一个持续10us的高电平
{Trig1(1);delay_us(10);Trig1(0);delay_us(10);
}#pragma vector=TIMER0_B1_VECTOR
__interrupt void TIMER0_B1_ISR(void)
{switch(__even_in_range(TB0IV,14)){case  0:break;                                 // No interruptcase  2:break;                          // CCR1 not usedcase  4:state =  TB0CCTL2 >> 14;TB0CCTL2 &= ~CCIFG;if( TB0CCTL2 & CM_1){cap_new = TB0CCR2;TB0CCTL2 &= ~CM_1;TB0CCTL2 |=  CM_2;}else if ( TB0CCTL2 & CM_2){cap_old = TB0CCR2;cap_data = ( cap_old - cap_new ) * 0.34 /50;TB0CCTL2 &= ~CM_2;TB0CCTL2 |=  CM_1;}else ;   break;             // 判断CM位捕捉模式 break;                         case  6: break;                 // reservedcase  8: break;                 // reservedcase 10: break;                 // reservedcase 12: break;                 // reservedcase 14:TB0CTL &= ~TBIFG;if(cap_old   < cap_new ){cap_N += 1;}break;                         default: break;}
}

更改主频后,需要对此进行修改cap_data = ( cap_old - cap_new ) * 0.34 /50;

最后

以上大概就是本次电赛我所使用到的一些东西,虽然最后成绩比价拉跨,但还是收获了很多,希望在将来还可以继续进步,不断学习,加油!

附录

整个工程文件,需要自取。

https://download.csdn.net/download/qq_53870874/86341614

MSP430F5529LP 2022电赛学习准备及相关例程相关推荐

  1. 2022电赛声源定位(基础篇)

    对于需要2022电赛题目的同学点击这个链接:https://pan.baidu.com/s/1zyC8MbgenAAQ_ZVmvFyZvg 提取码:g6kd 对于这个2022电赛E题声源定位的音频点击 ...

  2. 2022电赛F题思路

    2022电赛到现在为止已经出了结果.这是我第一次参加电赛,以前也没有相关的比赛经历,在这四天三夜的时间里能够和队友完成这样一项完整的作品,对我们来说都具有很大的意义.虽然最后还是有一些细节上的问题,不 ...

  3. 2022电赛C题:小车跟踪(方案1+核心代码)

    目录 前言 一.题目 二.方案1 1.材料清单 2.说明 三.核心代码 四.工程获取 前言 针对2022年电赛C题小车跟踪,本团队一共是做了两种方案:       第一种主要以摄像头(openmv)为 ...

  4. 2022电赛小车跟随行驶系统(C题)复盘

    此次的电赛感觉结束的挺突然的,在找到方向准备细化地进行调试的时候却是没有足够时间来完成代码上的完善.想着此次遗憾,写一篇博客来记录一下自己的经历吧,总结总结此次的电赛时光. 电赛题目 首先便是题目的选 ...

  5. 2022电赛省一-小车跟随行驶系统(C题)

    ⏩ 大家好哇!我是小光,嵌入式爱好者,一个想要成为系统架构师的大二学生. ⏩前段时间参加了电赛的校赛.七校联赛和省赛,校赛和七校联赛都获得了三等奖,省赛上也是获得了一等奖的好成绩

  6. 通过FPGA实现2022电赛F题

    这是本人第一次参加电赛,非常有收获,虽然电赛已经结束,不过并不影响把我的思路整理出来和大家交流一下,同时也为自己做个笔记,这里简单介绍一下思路,就不讲解程序了. 这次电赛的题目如下: 1.  设计思路 ...

  7. 2022 电赛陕西省赛

    一:题目: 声源定位跟踪系统(E题) 设计制作一个声源定位跟踪系统,能够实时显示及指示声源的位置,当声源移动时能够用激光笔动态跟踪声源. 设计并制作声音发生装置--"声源",装置最 ...

  8. 2022电赛五校联赛

    题目: 探测跟踪系统(C 题) 在区域内随便摆放易拉罐,能够探测并显示探测装置与目标物体之间的距离 l. 在区域内随便摆放多个易拉罐,探测跟踪系统能够探测并显示指定距离范围内的目标物体数量. 在区域内 ...

  9. 竞赛无人机搭积木式编程——以2022年TI电赛送货无人机一等奖复现为例学习(7月B题)

    在学习本教程前,请确保已经学习了前4讲中无人机相关坐标系知识.基础飞行控制函数.激光雷达SLAM定位条件下的室内定点控制.自动飞行支持函数.导航控制函数等入门阶段的先导教程. 同时用户在做二次开发自定 ...

最新文章

  1. java写游戏的聊天怎么写_怎么用JAVA编写一个打字游戏
  2. 排序算法一:选择排序
  3. css3 奇技淫巧 - 如何给小汽车换个背景色谈起
  4. 贝叶斯统计:信噪对偶与Dawid定理
  5. maven升级遇到的疑惑
  6. 探索测试 | 新奇深层测试策略之案例剖析(一)
  7. 项目案例第二篇中小型公司优化性能安全篇
  8. Route Class
  9. 【渝粤教育】电大中专药事管理与法规 (2)_1作业 题库
  10. docker镜像分层原理
  11. Python与Json、pickle模块
  12. Windows ping TCP端口工具之tcping
  13. ctf杂项各类编码汇总
  14. saltstack的探索-利用脚本增加用户
  15. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
  16. 《Java程序设计》在线课程使用说明-2021版
  17. baddy:核心函数入口
  18. 数据结构之冒泡排序的两个优化细节
  19. 转 SPOOLING技术——操作系统
  20. 学习 STM32之九轴姿态传感器(BWT901CL)串口通信读取数据

热门文章

  1. 2022年初级会计考试综合试题及答案
  2. php计算用户留存,利用Python计算新增用户留存率
  3. 计算机函数exp是什么意思,exp函数是什么意思
  4. 带SN切换流程_抖音频繁切换账号会限流吗?抖音频繁切换账号会降权吗?
  5. 洛谷 P8584 探索未知 题解
  6. 【PMP】PMP考试易错点总结和答题技巧总结
  7. 求单链表的最大值与原地逆转_数据结构精选考研试题.pdf
  8. 从粉丝经济看粉丝运营
  9. a标签 :focus的使用(:focus)
  10. Pytorch深度学习实战教程:UNet语义分割网络