将 PORTD 值存储在 pic18f452 的数组中 (C)
Storing PORTD value in array on pic18f452 (C)
我正在 Proteus 上开发 PIC18F452,正在寻求一些建议。
我的objective是每隔100ms(通过timer1设置)获取PORTDbits.RD0(设置为输入)的值,存入8位数组。该帧稍后将通过 SPI 发送到从机。
目前我只实现了我认为是数组的填充和位移。可悲的是,当我开始模拟时,只有数组的某个位在某些时候包含 PORTDbits.RD0.
的值
如果有人有什么想法可以提供帮助,那就太好了:D
这是我的代码
/* CONFIG *******************************************************************/
#pragma config PWRT = ON // Power-up Timer
#pragma config OSC = HS // High-Speed Oscillator
#pragma config LVP = OFF // Low-Voltage In-Circuit Serial Programming
#pragma config DEBUG = ON //
/* INCLUDES *****************************************************************/
#include "project_config.h" // All headers inclusion
/* MACROS *******************************************************************/
#define nop() {_asm nop _endasm}
/* DEFINES ******************************************************************/
#define SIZE 8
/* FUNCTIONS PROTOTYPES *****************************************************/
void main(void);
void isr_config(void);
void io_config(void);
void timer1_config(void);
void timer1_isr(void);
/* PROTOTYPES ***************************************************************/
/* VARIABLES DEFINITION *****************************************************/
unsigned int filling_cnt = 0;
/* MAIN *********************************************************************/
void main(void) {
unsigned char array[SIZE];
unsigned int index = 0;
int j;
/// Initialization
io_config();
timer1_config();
isr_config();
/// Interruption
timer1_isr();
/// Data acquisiton
while(1){
array[index] = PORTDbits.RD0; // Read RD0 and save in array
for(index = 0; index < SIZE; index++){ // Fill array
array[index] = array[index+1]; // shifting n_value to insert n+1_value
//printf("%s\n", array);
} //rof
filling_cnt++; // Array counter for filling control
if(filling_cnt > SIZE){ // Reached the end of array ?
index = 0; // Reset counter
printf("%s\n", array); // Send data to terminal
for (j=0; j<SIZE; j++){
array[j] = '[=10=]'; // Empty array
} //rof
} //fi
}
}
/* FUNCTIONS ****************************************************************/
/// Configurations
void timer1_config(void) {
T1CONbits.RD16 = 1; // Timer/Counter 8-bits/16-bits Control bit: 0=8-bits / 1=16-bits
T1CONbits.T1CKPS1 = 1; // Prescaler
T1CONbits.T1CKPS0 = 1; // 1 = 0b00
// 2 = 0b01
// 4 = 0b10
// 8 = 0b11
T1CONbits.T1OSCEN = 1; // Timer1 Oscillator shut off
T1CONbits.TMR1CS = 0; // Timer1 Clock Source Select bit
// 0 = Internal Clock (Fosc/4)
// 1 = Transition on T1CKI pin
T1CONbits.TMR1ON = 1; // Timer1 On/Off Control bit
// 1 = Enables Timer1
// 0 = Stops Timer1
TMR1H=0x0B; // Preset timer1 value for MSB register
TMR1L=0xDB; // Preset timer1 value for LSB register
// to get a 100ms delay
}
void isr_config(void) {
PIE1bits.TMR1IE = 1; // Enable Timer1 interrupts
PIR1bits.TMR1IF = 0; // Clear Timer1 interrupt flag
IPR1bits.TMR1IP = 1; // Non high priority interrupt
RCONbits.IPEN = 1; // Interrupt High level
INTCONbits.PEIE = 1; // All peripherals interrutps verified
INTCONbits.GIE = 1; // All interrupts verified
}
void io_config(void) {
TRISB = 0x00; // PORTB as output
TRISDbits.TRISD0 = 1; // COMP_OUT as input
TRISDbits.TRISD1 = 0; // DATA as output
}
/// Interruptions
#pragma code highVector = 0x08 //lowVector = 0x18
void InterruptHigh (void) {
_asm
goto timer1_isr
_endasm
}
#pragma code
#pragma interrupt timer1_isr
void timer1_isr(void) {
if (PIR1bits.TMR1IF == 1) { // check that timer1 overflow is reason for ISR.
// even though there is only one Interrupt source
// trigger enabled, it is good programming practice to
// test why we have arrived at the ISR.
PIR1bits.TMR1IF = 0; // Timer1 interrupt flag clear
TMR1H = 0x0B; // Preset timer1 value for MSB register
TMR1L = 0xDC; // Preset timer1 value for LSB register
// with a 20MHz xtal, Timer1 Prescalar set to /8
// decimal 3036 (0x0B 0xDC) is the counter start point
// which will result in Timer1 overflow 1 per 100ms
// 65536 - 3036 = 62500 cycles
// 10 interrupts per second
LATBbits.LATB4 = !LATBbits.LATB4; // invert the condition of LED to show program
// has entered the Interrupt routine
PORTDbits.RD1 = !PORTDbits.RD1; // invert the condition of DATA to show program
// has entered the Interrupt routine
} //fi
}
/* EOF main.c ***************************************************************/
如果此消息中有任何遗漏或不清楚的地方,请随时告诉我。我会尽力添加细节或重新考虑我的 post 以促进理解。
提前致谢 ;)
- 在 main 函数中有一个无限循环,它在两次采集之间没有任何延迟地运行。您需要的是两次读取 PORTD 之间有 100ms 的延迟。
您可以做的是引入一个全局标志。这在定时器子程序中设置,并在 main 中清除。
- 将数据填充到数组中的代码不正确。下面的代码按顺序从位置
arrray[0]
、array[1]
到最大值填充数组。
计时器应该这样修改
void timer1_isr(void) {
if (PIR1bits.TMR1IF == 1) {
blTimeOverFlag = 1;
// Other code here
}
}
主函数循环如下
while(1){
if (blTimeOverFlag == 1)
{
blTimeOverFlag = 0;
array[filling_cnt] = PORTDbits.RD0; // Read RD0 and save in array
filling_cnt++; // Array counter for filling control
if(filling_cnt >= SIZE){ // Reached the end of array ?
filling_cnt = 0;
printf("%s\n", array); // Send data to terminal
for (j=0; j<SIZE; j++){
array[j] = '[=11=]'; // Empty array
} //rof
} //fi
}
}
我正在 Proteus 上开发 PIC18F452,正在寻求一些建议。
我的objective是每隔100ms(通过timer1设置)获取PORTDbits.RD0(设置为输入)的值,存入8位数组。该帧稍后将通过 SPI 发送到从机。
目前我只实现了我认为是数组的填充和位移。可悲的是,当我开始模拟时,只有数组的某个位在某些时候包含 PORTDbits.RD0.
的值如果有人有什么想法可以提供帮助,那就太好了:D
这是我的代码
/* CONFIG *******************************************************************/
#pragma config PWRT = ON // Power-up Timer
#pragma config OSC = HS // High-Speed Oscillator
#pragma config LVP = OFF // Low-Voltage In-Circuit Serial Programming
#pragma config DEBUG = ON //
/* INCLUDES *****************************************************************/
#include "project_config.h" // All headers inclusion
/* MACROS *******************************************************************/
#define nop() {_asm nop _endasm}
/* DEFINES ******************************************************************/
#define SIZE 8
/* FUNCTIONS PROTOTYPES *****************************************************/
void main(void);
void isr_config(void);
void io_config(void);
void timer1_config(void);
void timer1_isr(void);
/* PROTOTYPES ***************************************************************/
/* VARIABLES DEFINITION *****************************************************/
unsigned int filling_cnt = 0;
/* MAIN *********************************************************************/
void main(void) {
unsigned char array[SIZE];
unsigned int index = 0;
int j;
/// Initialization
io_config();
timer1_config();
isr_config();
/// Interruption
timer1_isr();
/// Data acquisiton
while(1){
array[index] = PORTDbits.RD0; // Read RD0 and save in array
for(index = 0; index < SIZE; index++){ // Fill array
array[index] = array[index+1]; // shifting n_value to insert n+1_value
//printf("%s\n", array);
} //rof
filling_cnt++; // Array counter for filling control
if(filling_cnt > SIZE){ // Reached the end of array ?
index = 0; // Reset counter
printf("%s\n", array); // Send data to terminal
for (j=0; j<SIZE; j++){
array[j] = '[=10=]'; // Empty array
} //rof
} //fi
}
}
/* FUNCTIONS ****************************************************************/
/// Configurations
void timer1_config(void) {
T1CONbits.RD16 = 1; // Timer/Counter 8-bits/16-bits Control bit: 0=8-bits / 1=16-bits
T1CONbits.T1CKPS1 = 1; // Prescaler
T1CONbits.T1CKPS0 = 1; // 1 = 0b00
// 2 = 0b01
// 4 = 0b10
// 8 = 0b11
T1CONbits.T1OSCEN = 1; // Timer1 Oscillator shut off
T1CONbits.TMR1CS = 0; // Timer1 Clock Source Select bit
// 0 = Internal Clock (Fosc/4)
// 1 = Transition on T1CKI pin
T1CONbits.TMR1ON = 1; // Timer1 On/Off Control bit
// 1 = Enables Timer1
// 0 = Stops Timer1
TMR1H=0x0B; // Preset timer1 value for MSB register
TMR1L=0xDB; // Preset timer1 value for LSB register
// to get a 100ms delay
}
void isr_config(void) {
PIE1bits.TMR1IE = 1; // Enable Timer1 interrupts
PIR1bits.TMR1IF = 0; // Clear Timer1 interrupt flag
IPR1bits.TMR1IP = 1; // Non high priority interrupt
RCONbits.IPEN = 1; // Interrupt High level
INTCONbits.PEIE = 1; // All peripherals interrutps verified
INTCONbits.GIE = 1; // All interrupts verified
}
void io_config(void) {
TRISB = 0x00; // PORTB as output
TRISDbits.TRISD0 = 1; // COMP_OUT as input
TRISDbits.TRISD1 = 0; // DATA as output
}
/// Interruptions
#pragma code highVector = 0x08 //lowVector = 0x18
void InterruptHigh (void) {
_asm
goto timer1_isr
_endasm
}
#pragma code
#pragma interrupt timer1_isr
void timer1_isr(void) {
if (PIR1bits.TMR1IF == 1) { // check that timer1 overflow is reason for ISR.
// even though there is only one Interrupt source
// trigger enabled, it is good programming practice to
// test why we have arrived at the ISR.
PIR1bits.TMR1IF = 0; // Timer1 interrupt flag clear
TMR1H = 0x0B; // Preset timer1 value for MSB register
TMR1L = 0xDC; // Preset timer1 value for LSB register
// with a 20MHz xtal, Timer1 Prescalar set to /8
// decimal 3036 (0x0B 0xDC) is the counter start point
// which will result in Timer1 overflow 1 per 100ms
// 65536 - 3036 = 62500 cycles
// 10 interrupts per second
LATBbits.LATB4 = !LATBbits.LATB4; // invert the condition of LED to show program
// has entered the Interrupt routine
PORTDbits.RD1 = !PORTDbits.RD1; // invert the condition of DATA to show program
// has entered the Interrupt routine
} //fi
}
/* EOF main.c ***************************************************************/
如果此消息中有任何遗漏或不清楚的地方,请随时告诉我。我会尽力添加细节或重新考虑我的 post 以促进理解。 提前致谢 ;)
- 在 main 函数中有一个无限循环,它在两次采集之间没有任何延迟地运行。您需要的是两次读取 PORTD 之间有 100ms 的延迟。
您可以做的是引入一个全局标志。这在定时器子程序中设置,并在 main 中清除。
- 将数据填充到数组中的代码不正确。下面的代码按顺序从位置
arrray[0]
、array[1]
到最大值填充数组。
计时器应该这样修改
void timer1_isr(void) {
if (PIR1bits.TMR1IF == 1) {
blTimeOverFlag = 1;
// Other code here
}
}
主函数循环如下
while(1){
if (blTimeOverFlag == 1)
{
blTimeOverFlag = 0;
array[filling_cnt] = PORTDbits.RD0; // Read RD0 and save in array
filling_cnt++; // Array counter for filling control
if(filling_cnt >= SIZE){ // Reached the end of array ?
filling_cnt = 0;
printf("%s\n", array); // Send data to terminal
for (j=0; j<SIZE; j++){
array[j] = '[=11=]'; // Empty array
} //rof
} //fi
}
}