hello , i am having some problems with the multiplication division unit of the xc878 infineon microcontroller. i am trying to do a shift operation. the number to be shifted is a 32 bit. lets say i want to do this: 0x00FB00FF >> 16. i would require the MD0,MD1,MD2,MD3 registers. now my problem. i can load the MD0 and MD1 registers but i dont know how to load the MD2 and MD3 registers. please kindly help out. stephen
This is how you can do it in assembly language:
#include <xc878.h> ULSHR: MOV A,R0 JZ RETURN ANL A,#1FH ORL A,#20H MOV MDU_MD0,R7 MOV MDU_MD1,R6 MOV MDU_MD2,R5 MOV MDU_MD3,R4 MOV MDU_MDUCON,A LCALL ?C?WAIT18 ;WAIT 18 CYCLES MOV R7,MDU_MD0 MOV R6,MDU_MD1 MOV R5,MDU_MD2 MOV R4,MDU_MD3 RETURN: RET
Note that this code is not tested, you should verify (using the datasheet) that it is working with the MDU of the XC878.
hello everyone,
thanks for your quick reply. i was wondering if it is possible to do that in C too. i am not familiar with Assembler. here is what i did i C. The function Shift_MDU gets two Parameters. param_5 is a 32bit number and param_6 is the number of shift to be performed. MDU_MD01 and MDU_MD23 are 16bit Registers. when i assign the 32 bit varaible(param_5) to the MDU_MD01, it automatically reads the 16 lower bits. now i cant seem to be able to read the other 16 high bits into the MDU_MD23 Register.
int Shift_MDU(long int param_5, int param_6)
{
SYSCON0 |= 0x01;
MDU_MD01 = param_5; MDU_MD23 = param_5; // dont know how to load this. MDU_MDUCON = 0x13; MDU_MD4 = 0x20 | param_6; // MDU_MD23=(param_5 & 0xFFFF0000)>> 16; // this is what should be loaded in the MD23 register while(MDU_BSY==1); erg_shift = (MDU_MR01); SYSCON0 &= ~(ubyte)0x01;
return erg_shift;
}
You would normally do:
MDU_MD01 = param_5; MDU_MD23 = param_5 >> 16;
and often even show the compiler that you know about the difference in size between left-hand and right-hand side of the assign:
MDU_MD01 = (uint16_t)param_5; MDU_MD23 = (uint16_t)(param_5 >> 16);
The compiler should be smart enough to figure out that a shift right with 16 steps for the second assign is the same as picking up the two most significant bytes - so no real shifting performed.
Personally, I would prefer a function that accesses 32-bit physical registers to use int32_t or uint32_t as argument type instead of using long int or unsigned long - but it isn't too important since the full function is most definitely not portable anyway. Note that uint16_t etc require that you #include <stdint.h>
Hello,
thanks for that tip. but unfortunately the C51 Compiler still does the shifting. actually i am using the MDU to make shifting faster but if i end up shifting again then it doesnt make much sense. any other idea how this Problem can be solved? actually the datasheet says the MDU can handle 32 bit shift, so i cant seem to understand why it doesnt recognise 32 bit variable.
Another solution, if the compiler performs 16-bit shifts as actual shifts, is to use a pointer to a struct of two uint16_t integers and assign (with type cast) this pointer the address of the 32-bit integer. Then individually do
p = (u32_to_u16_struct*)&my_32_bit_val; MDU_MD01 = p->low16; MDU_MD23 = p->high16;
I recommend to use an assembly module.
I believe that the Infineon XC800 is compatible with this http://www.keil.com/support/man/docs/c51/c51_mdu_r515.htm
Using the MDU_R515 directive should therefore automatically use the MDU.