关于*((volatile int*)0x0000xxxx)

本文介绍如何使用C语言向指定地址的寄存器写入数据,并解释了使用volatile关键字的原因,确保编译器不会优化掉关键指令。

向某个寄存器(地址0x56000000)写入数据0x010,用c怎么写呢?

首先看如下例子:

int a;
int *p;
p=&a;

如果让a=0x010,只需要a=0x010或*p=0x010

这里p是a的地址,如果a的地址为0x56000000,那么p=0x56000000,用c怎么表示呢?

答案为:p=(int *)0x56000000

那么如果给这个地址赋值0x010,就可以写为:*((int *)0x56000000)=0x010

因为这是给寄存器赋值,为了防止编译器优化掉,需要加volatile,于是就写为:

*((volatile int *)0x56000000)=0x010

那么标准的写法如下:

#define REG  *((volatile int *)0x56000000)

REG=0x010;

我使用的是BAT32G135,然后我现在想实现传输时,采用数据帧格式——开始符|数据序列|数据|数据长度|结束符 具体为 0xAA | xx | xxxx | xx | 0xFF 单片机检测到结束符后,发送一个”0xAA”作为ACK回应标志,意味成功接受数据,当超过200ms,未接收到数据,则接受失败返回”0xBB”作为NACK位,重传数据。 我现有的代码是这些#include "BAT32G135.h" #include "string.h" #include "stdint.h" #include "userdefine.h" #include "sci.h" #define FRAME_START 0xAA #define FRAME_END 0xFF #define ACK_FLAG 0xAA #define NACK_FLAG 0xBB #define UART_BUF_SIZE 64 #define TIME_OUT_LIMIT 200 // 接收状态机状态定义 typedef enum { RX_STATE_IDLE, // 等待开始符 RX_STATE_SEQ, // 接收序列号 RX_STATE_DATA, // 接收数据 RX_STATE_LEN, // 接收长度字段 RX_STATE_END // 等待结束符 } rx_state_t; volatile uint8_t uart_buf[UART_BUF_SIZE] ; volatile uint8_t uart_index = 0; volatile uint8_t frame_ready = 0; volatile uint16_t timeout_counter = 0; volatile uint8_t receiving = 0; void UART0_SendString(const char *str) { while (*str != '\0') { UART0_Send((uint8_t)*str); // 发送当前字符 str++; // 移动到下一个字符 } } void UART_ReceiveHandler(uint8_t byte) { receiving =1; timeout_counter = 0; if(uart_index == 0){ if (byte == FRAME_START){ uart_buf[0]=byte; uart_index = 1 ; } return; } uart_buf[uart_index++]=byte; if(uart_index>=UART_BUF_SIZE) uart_index=UART_BUF_SIZE-1; if (byte == FRAME_END) { frame_ready =1; receiving = 0; } } void Timer_ISR(void) { if (receiving) { timeout_counter++; if (timeout_counter>=TIME_OUT_LIMIT) { UART0_Send(NACK_FLAG); uart_index=0; receiving=0; timeout_counter=0; } } } void UART0_IRQHandler (void) { uint8_t byte ; if (SCI0->ST0& (1<<0)) {byte=SCI0->SDR00; UART_ReceiveHandler(byte); SCI0->ST0=(1<<0); } } void UART_TASK(void) { if (frame_ready) { uint8_t seq=uart_buf[1]; uint8_t len=uart_buf[uart_index-2]; if (uart_index==(len+4)) { UART0_Send(ACK_FLAG); } else { UART0_Send(NACK_FLAG); } memset((void*)uart_buf,0,UART_BUF_SIZE); uart_index=0; frame_ready =1; } } 但我需要进行修改才能够使用,我提供一下库里的函数,请结合库里的函数对我现有的代码进行修改 void UART0_Send(uint8_t ch) { SCI0->TXD0 = ch; while (SCI0->SSR00 & (_0040_SCI_UNDER_EXECUTE | _0020_SCI_VALID_STORED)) { ; } return; } /*********************************************************************************************************************** * Function Name: UART0_Receive * @brief This function receives UART0 data. * @param None * @return char ***********************************************************************************************************************/ char UART0_Receive() { while ((SCI0->SSR01 & _0020_SCI_VALID_STORED) == 0) { ; } return SCI0->RXD0; }#include "userdefine.h" #include "BAT32G135.h" #include "sci.h" /*********************************************************************************************************************** Pragma directive ***********************************************************************************************************************/ #if defined USE_SCI_UART2_TX void IRQ07_Handler(void) __attribute__((alias("uart2_interrupt_send"))); #elif defined USE_SCI_SPI20 void IRQ07_Handler(void) __attribute__((alias("spi20_interrupt"))); #elif defined USE_SCI_IIC20 void IRQ07_Handler(void) __attribute__((alias("iic20_interrupt"))); #endif #if defined USE_SCI_UART2_RX void IRQ08_Handler(void) __attribute__((alias("uart2_interrupt_receive"))); #elif defined USE_SCI_SPI21 void IRQ08_Handler(void) __attribute__((alias("spi21_interrupt"))); #elif defined USE_SCI_IIC21 void IRQ08_Handler(void) __attribute__((alias("iic21_interrupt"))); #endif #if defined USE_SCI_UART0_TX void IRQ10_Handler(void) __attribute__((alias("uart0_interrupt_send"))); #elif defined USE_SCI_SPI00 void IRQ10_Handler(void) __attribute__((alias("spi00_interrupt"))); #elif defined USE_SCI_IIC00 void IRQ10_Handler(void) __attribute__((alias("iic00_interrupt"))); #endif #if defined USE_SCI_UART0_RX void IRQ11_Handler(void) __attribute__((alias("uart0_interrupt_receive"))); #elif defined USE_SCI_SPI01 void IRQ11_Handler(void) __attribute__((alias("spi01_interrupt"))); #elif defined USE_SCI_IIC00 void IRQ11_Handler(void) __attribute__((alias("iic01_interrupt"))); #endif #if defined USE_SCI_UART1_TX void IRQ13_Handler(void) __attribute__((alias("uart1_interrupt_send"))); #elif defined USE_SCI_SPI10 void IRQ13_Handler(void) __attribute__((alias("spi10_interrupt"))); #elif defined USE_SCI_IIC10 void IRQ13_Handler(void) __attribute__((alias("iic10_interrupt"))); #endif #if defined USE_SCI_UART1_RX void IRQ14_Handler(void) __attribute__((alias("uart1_interrupt_receive"))); #elif defined USE_SCI_SPI11 void IRQ14_Handler(void) __attribute__((alias("spi11_interrupt"))); #elif defined USE_SCI_IIC11 void IRQ14_Handler(void) __attribute__((alias("iic11_interrupt"))); #endif /*********************************************************************************************************************** Global variables and functions ***********************************************************************************************************************/ volatile uint8_t g_iic00_tx_end; /* iic00 send data end */ volatile uint8_t g_iic00_rx_end; /* iic00 receive data end */ volatile uint8_t g_iic01_tx_end; /* iic01 send data end */ volatile uint8_t g_iic01_rx_end; /* iic01 receive data end */ volatile uint8_t g_iic10_tx_end; /* iic10 send data end */ volatile uint8_t g_iic10_rx_end; /* iic10 receive data end */ volatile uint8_t g_iic11_tx_end; /* iic11 send data end */ volatile uint8_t g_iic11_rx_end; /* iic11 receive data end */ volatile uint8_t g_iic20_tx_end; /* iic20 send data end */ volatile uint8_t g_iic20_rx_end; /* iic20 receive data end */ volatile uint8_t g_iic21_tx_end; /* iic21 send data end */ volatile uint8_t g_iic21_rx_end; /* iic21 receive data end */ /* Start user code for global. Do not edit comment generated here */ /* End user code. Do not edit comment generated here */ /*********************************************************************************************************************** * Function Name: uart0_interrupt_receive * @brief UART0 Receive interrupt service routine * @param None * @return None ***********************************************************************************************************************/ void uart0_interrupt_receive(void) { volatile uint8_t rx_data; volatile uint8_t err_type; INTC_ClearPendingIRQ(SR0_IRQn); err_type = (uint8_t)(SCI0->SSR01 & 0x0007U); SCI0->SIR01 = (uint16_t)err_type; if (err_type != 0U) { uart0_callback_error(err_type); } rx_data = SCI0->RXD0; if (g_uart0_rx_length > g_uart0_rx_count) { *gp_uart0_rx_address = rx_data; gp_uart0_rx_address++; g_uart0_rx_count++; if (g_uart0_rx_length == g_uart0_rx_count) { uart0_callback_receiveend(); } } else { uart0_callback_softwareoverrun(rx_data); } } /*********************************************************************************************************************** * Function Name: uart0_interrupt_send * @brief UART0 Send interrupt service routine * @param None * @return None ***********************************************************************************************************************/ void uart0_interrupt_send(void) { INTC_ClearPendingIRQ(ST0_IRQn); if (g_uart0_tx_count > 0U) { SCI0->TXD0 = *gp_uart0_tx_address; gp_uart0_tx_address++; g_uart0_tx_count--; } else { uart0_callback_sendend(); } } /*********************************************************************************************************************** * Function Name: uart0_callback_receiveend * @brief This function is a callback function when UART0 finishes reception. * @param None * @return None ***********************************************************************************************************************/ static void uart0_callback_receiveend(void) { /* Start user code. Do not edit comment generated here */ /* End user code. Do not edit comment generated here */ } /*********************************************************************************************************************** * Function Name: uart0_callback_softwareoverrun * @brief This function is a callback function when UART0 receives an overflow data. * @param rx_data - receive data * @return None ***********************************************************************************************************************/ static void uart0_callback_softwareoverrun(uint16_t rx_data) { /* Start user code. Do not edit comment generated here */ /* End user code. Do not edit comment generated here */ } /*********************************************************************************************************************** * Function Name: uart0_callback_sendend * @brief This function is a callback function when UART0 finishes transmission. * @param None * @return None ***********************************************************************************************************************/ static void uart0_callback_sendend(void) { /* Start user code. Do not edit comment generated here */ /* End user code. Do not edit comment generated here */ } /*********************************************************************************************************************** * Function Name: uart0_callback_error * @brief This function is a callback function when UART0 reception error occurs. * @param err_type - error type value * @return None ***********************************************************************************************************************/ static void uart0_callback_error(uint8_t err_type) { /* Start user code. Do not edit comment generated here */ /* End user code. Do not edit comment generated here */ }
最新发布
10-16
/**********************************************头文件区**********************************************/ #include <REGX51.H> /**********************************************变量声明区**********************************************/ sbit input = P3^2; //方波输入引脚 unsigned char code Seg_Dula[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,//0~9 0x71,//F 0x73//P }; //段码存放数组 unsigned char code Seg_Wela[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//位码存放数组 unsigned char Seg_Buf[] = {10,10,10,10,10,10,10,10};//数码管显示数据存放数组 unsigned char Seg_Pos; //数码管扫描变量 unsigned char Seg_Slow_Down; //数码管减速变量 unsigned int time_1,time_2; //占空比测量时间计数变量 volatile unsigned int freq = 0; //频率计数变量 unsigned char pwm=0; //占空比显示变量 unsigned long k; //占空比辅助计算变量 /**********************************************函数处理区**********************************************/ /*******数码管显示函数*******/ void Seg_Disp(unsigned char wela,dula) { P0 = 0x00; //段选消影 P2_6 = 1; P2_6 = 0; P0 = Seg_Wela[wela]; //读取位选 P2_7 = 1; P2_7 = 0; P0 = Seg_Dula[dula]; //读取段选 P2_6 = 1; P2_6 = 0; } /*******显示处理函数*******/ void Seg_Proc() { if(Seg_Slow_Down < 100) return; //数码管减速刷新 Seg_Slow_Down = 0; // 频率显示格式: F XXXX (高位熄灭) // 占空比显示格式: P XX Seg_Buf[5] = 12; Seg_Buf[6] = pwm / 10; Seg_Buf[7] = pwm % 10; } /*******定时器0初始化(1ms中断)*******/ void Timer0_Init(void) //1毫秒@12.000MHz { TMOD &= 0xF0; //设置定时器模式 TMOD |= 0x01; //设置定时器模式 TL0 = 0x18; //设置定时初始值 TH0 = 0xFC; //设置定时初始值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 ET0 = 1; EA = 1; //启用定时器 } /*******定时器1初始化(用于占空比测量)*******/ void Timer1_Init() { TMOD |= 0x10; // Timer1为16位定时器 } /*******Timer0中断服务函数*******/ void Timer0_ISR() interrupt 1 { TL0 = 0x18; //设置定时初始值 TH0 = 0xFC; //设置定时初始值 Seg_Slow_Down++; Seg_Pos = (++Seg_Pos)%8; Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos]); // 数码管动态扫描 while(input);//等待高电平时间过去 while(!input);//等待低电平时间过去 TR1=1;//启动定时器1 while(input);//等待计时完成 time_1=TH1; //记录高电平时间 time_1=time_1*256+TL1; while(!input);//等待周期结束 TR1=0;//停止定时器1 time_2=TH1; //记录周期时间 time_2=time_2*256+TL1; k=time_1;//计算占空比 k=k*100; k=k/time_2; pwm=k; freq = 1000000 / time_2; //频率转换 TH1=0;TL1=0; } /**********************************************主函数**********************************************/ void main() { Timer1_Init(); // 初始化定时器1 Timer0_Init(); // 初始化定时器0 while (1) { Seg_Proc(); } }生成以上代码流程图
06-21
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值