使用宏灵活的控制代码

这个系列记录了前一个项目中的一些心得,《接下来一段时间的工作》列了一个目录。不过具体记录时,没有按照目录的顺序。

第一篇记一下关于宏的一些使用。

有一些(特别是纯C++)程序猿,认为宏在代码中的作用不大,尤其是使用const XXX代替宏的号召使得很多刚开始学习C或者转为C++的人放弃了使用宏。其实宏有很多用处,尤其是纯C或者嵌入式编程中,比如:

1.求一个结构体中某类型的偏移量、字节数等

2.位运算等

3.求地址、取高低位等

...

不过这些都是处理一些技术细节上的技巧,我想说的是在大型项目中如何使用宏技巧来控制代码,中间有一些方法日常写代码可会用到。

1.错综复杂的头文件包含时,用#ifdef...组合来防止头文件重复包含(略过...)

2.跨平台

   不同平台下不同编译器对C/C++的标准执行的不一致,因此如果考虑到后面有跨平台项目的移植问题,那么在项目代码的基础库中最好使用宏将一些基础关键字定义

3.使用宏定义具有本项目特色的变量类型(typedef也可以)

  example:

   #deine int MyPrjInt

4.dll导出

   大型项目多包含n个dll,各种功能块由不同的程序猿分别实现,他们向外输出dll供别人使用,所以就存在dll导出函数和导出类的问题。使用宏可以很方便的控制这些逻辑。

   example:


                
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: #include <msp430.h> int main( void ) { // Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; // Set MOSI, MISO, SCLK as output pins P1DIR |= BIT1 + BIT2 + BIT5; // Set MOSI low, SCLK low P1OUT &= ~(BIT1 + BIT5); // Set MISO as input pin P1DIR &= ~BIT2; // Set SCLK as source of timer A0 TACTL = TASSEL_2 + MC_1; // SMCLK = 16MHz/8 = 2MHz TACCR0 = 2 - 1; TACCTL0 = CCIE; // Set USCI in SPI mode UCB0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC; UCB0CTL1 |= UCSSEL_2; // Set clock divider UCB0BR0 = 8; UCB0BR1 = 0; UCB0CTL1 &= ~UCSWRST; // Enable interrupts _BIS_SR(GIE); // Send data UCB0TXBUF = 0xAA; while (1) { // Wait for data to be received while (!(IFG2 & UCB0RXIFG)); // Read data unsigned int data = UCB0RXBUF; } return 0; }中文翻译:#include <msp430.h> int main( void ) { // 停止看门狗定时器以防止超时复位 WDCTL = WDTPW + WDTHOLD; // 将MOSI,MISO,SCLK设置为输出引脚 P1DIR |= BIT1 + BIT2 + BIT5; // 将MOSI设置为低电平,SCLK设置为低电平 P1OUT &= ~(BIT1 + BIT5); // 将MISO设置为输入引脚 P1DIR &= ~BIT2; // 将SCLK设置为定时器A0的源 TACTL = TASSEL_2 + MC_1; // SMCLK = 16MHz/8 = 2MHz TACCR0 = 2 - 1; TACCTL0 = CCIE; // 设置USCI为SPI模式 UCB0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC; UCB0CTL1 |= UCSSEL_2; // 设置时钟分频器 UCB0BR0 = 8; UCB0BR1 = 0; UCB0CTL1 &= ~UCSWRST; // 使能中断 _BIS_SR(GIE); // 发送数据 UCB0TXBUF = 0xAA; while (1) { // 等待接收数据 while (!(IFG2 & UCB0RXIFG)); // 读取数据 unsigned int data = UCB0RXBUF; } return 0; } ### 回答2: MSP430是德州仪器(Texas Instruments)推出的一系列低功耗微控制器,其中的SPI(串行外设接口)是一种常用的通信协议。下面是一个基于MSP430的SPI控制代码示例。 ```c #include <msp430.h> #define SS BIT4 // Slave Select(P1.4) #define SCLK BIT5 // Serial Clock(P1.5) #define MOSI BIT6 // Master Output, Slave Input(P1.6) #define MISO BIT7 // Master Input, Slave Output(P1.7) void SPI_Init() { P1SEL |= SCLK + MOSI + MISO; // 配置SPI引脚 P1SEL2 |= SCLK + MOSI + MISO; // 配置SPI引脚 UCB0CTL1 |= UCSWRST; // SPI控制器复位 UCB0CTL0 = UCCKPL + UCMSB + UCMST + UCMODE_0 + UCSYNC; // 配置通信模式 UCB0BR0 = 0x02; // 时钟分频设置 UCB0BR1 = 0; UCB0CTL1 &= ~UCSWRST; // SPI控制器复位 IE2 |= UCB0RXIE; // 使能SPI接收中断 } void SPI_Transmit(unsigned char data) { UCB0TXBUF = data; // 发送数据 while (!(IFG2 & UCB0TXIFG)) ; // 等待发送完成 } unsigned char SPI_Receive() { while (!(IFG2 & UCB0RXIFG)) ; // 等待接收完成 return UCB0RXBUF; // 返回接收到的数据 } void main(void) { WDTCTL = WDTPW + WDTHOLD; // 停用看门狗定时器 SPI_Init(); // 初始化SPI __enable_interrupt(); // 允许中断 while(1) { P1OUT |= SS; // Slave Select置高 __delay_cycles(10000); // 稍作延时 SPI_Transmit(0x55); // 发送数据0x55 unsigned char receivedData = SPI_Receive(); // 接收数据 // 进行后续处理 P1OUT &= ~SS; // Slave Select置低 __delay_cycles(10000); // 稍作延时 } } ``` 上述代码首先定义了SPI通信所需的引脚,并在初始化函数`SPI_Init()`中配置了SPI的相关参数。其中`SPI_Transmit()`函数用于发送数据,`SPI_Receive()`函数用于接收数据。 在主函数中,可以根据需要进行数据的发送和接收操作。在给定的示例中,指定发送数据为0x55,并接收数据后进行了后续处理。 在程序运行时,首先将Slave Select引脚置高,发送数据后等待接收完成并返回接收数据,然后再将Slave Select引脚置低,以完成一次SPI通信。 以上是一个基于MSP430的简单SPI控制代码示例,你可以根据实际需求进行相应的修改和扩展。 ### 回答3: MSP430是一种低功耗的微控制器,具有强大的功能和灵活的外设,包括SPI(串行外设接口)。下面是一个基于MSP430的SPI控制代码示例: 首先,需要包含MSP430的SPI头文件和所需的定义: #include <msp430.h> #define SS_PIN BIT4 // 选择SPI从器件的片选引脚 #define CLK_PIN BIT5 // 设置SPI时钟引脚 #define MOSI_PIN BIT6 // 设置SPI主机输出器件输入引脚 #define MISO_PIN BIT7 // 设置SPI主机输入器件输出引脚 接下来,初始化SPI外设和相关IO: void SpiInit() { P1DIR |= SS_PIN; // 将SPI从器件片选引脚设置为输出 P1SEL |= BIT1 + CLK_PIN + MOSI_PIN + MISO_PIN; // 配置SPI引脚功能 P1SEL2 |= BIT1 + CLK_PIN + MOSI_PIN + MISO_PIN; UCB0CTL1 |= UCSWRST; // 禁用SPI控制器 UCB0CTL0 = UCCKPH + UCMSB + UCMST + UCMODE_0 + UCSYNC; // 配置SPI主模式,高位在前,时钟相位为第一个边沿,同步模式 UCB0CTL1 |= UCSSEL_2; // 使用SMCLK作为SPI时钟源 UCB0BR0 = 0x02; // 设置SPI时钟分频为2,产生较低的SPI时钟速率 UCB0BR1 = 0; UCB0CTL1 &= ~UCSWRST; // 启用SPI控制器 } 编写SPI数据传输函数: void SpiSend(unsigned char data) { while(!(IFG2 & UCB0TXIFG)); // 等待当前传输完成 UCB0TXBUF = data; // 发送数据 } unsigned char SpiReceive() { while(!(IFG2 & UCB0RXIFG)); // 等待接收到数据 return UCB0RXBUF; // 返回接收到的数据 } 最后,在主函数中使用这些函数进行SPI数据传输: int main(void) { WDTCTL = WDTPW + WDTHOLD; // 停用看门狗定时器 BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; SpiInit(); // 初始化SPI外设 unsigned char sendData = 0xAA; unsigned char receiveData; // 发送数据 P1OUT &= ~SS_PIN; // 片选拉低,选择SPI从器件 SpiSend(sendData); // 发送数据 P1OUT |= SS_PIN; // 片选拉高,完成数据传输 // 接收数据 P1OUT &= ~SS_PIN; // 片选拉低,选择SPI从器件 receiveData = SpiReceive(); // 接收数据 P1OUT |= SS_PIN; // 片选拉高,完成数据传输 return 0; } 希望以上代码能帮到您,如有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值